Sách HỌC TIẾNG ANH
SONG NGỮ cho
LẬP TRÌNH VIÊN (Phần 1)
HỆ THỐNG ĐÀO TẠO LẬP TRÌNH HIỆN ĐẠI
Phiên bản 1.0 - Tháng 02/2022
LI M ĐẦU
Lp trình viên mun gii tiếng Anh "như gii code", ngoài nhng phương pháp
hc đơn thun như xem phim, hc qua bài hát, video thì vic hc qua nhng bài
mu song ng đã highlight cm t quan trng cũng cùng thú v hiu
qu.
"Sách Song Ng Cho Lp Trình Viên (Phn 1)" được biên tp theo chương
"Principles, Patterns, and Practices" t cun sách "Agile Software Development"
ca tác gi Robert C. Martin. Ni dung k v nhân vt Alphonse, mt sinh viên IT
mi ra trường
được nhn vào thc tp công ty ca ông C (chính tác gi).
Thông qua nhng câu chuyn, tình hung, bài hc khi mi đặt chân vào ngành
công nghip phn mm được k li t dưới chính góc nhìn Alphonse, các bn
th:
- Được tiếp cn vi ngôn ng chun hơn
- Được m mang hiu biết thông qua ngun kiến thc, ý tưởng ca tác gi t
các bài mu Anh - Vit
- Va được tiếp xúc vi tiếng Anh, va được ôn li nhng bài toán lp trình cơ
bn
Mc đội ngũ biên tp ca CodeGym đã
n lc trong vic hoàn thin cun
sách này vi tiêu chí d hiu, khoa hc hiu qu, tuy nhiên khó để tránh khi
các sai sót trong quá trình biên son. vy, chúng mình rt mong nhn được
các ý kiến phn hi đóng góp ca mi người thông qua email
marketing@codegym.vn.
Cm ơn các bn đã ti đọc "Sách Song Ng Cho Lp Trình Viên (Phn 1)".
Đừng quên chia s tài liu này để chúng mình thêm động lc biên son các
phn tiếp theo ca cun sách nhé.
Thân,
Ban biên tp.
while(!(success = try()));while(!(success = try()));
LI M ĐẦU 1
Th lành ngh #1 - M đầu Thm ha 3
Th lành ngh #2 - Chế độ ăn kiêng tăng cường 8
Th lành ngh #3:Tính rõ ràng và cng tác 16
Th lành ngh #4 - Bài kim tra tính kiên nhn 24
Th lành ngh #5: Bước nh 30
Danh sách t vng tng hp 45
PH LC: TÀI NGUYÊN LP TRÌNH 52
while(!(success = try()));while(!(success = try()));
www.codegym.vn / Page 02
Th lành ngh #1 - M đầu Thm ha
13 February 2002,
Dear Diary,
Today was a disaster I really messed
it up. I wanted so much to impress the
journeymen here, but all I did was
make a mess.
It was my first day on the job as an
apprentice to Mr. C. I was lucky to get
this apprenticeship. Mr. C is a
well-recognized master of software
development. The competition for this
position was fierce.
Mr. C’s apprentices often become
journeymen in high demand. It means
something to
have worked with Mr. C.
Ngày 13 tháng 2 năm 2002.
Nht ký thân mến,
Ngày hôm nay đúng mt thm ho
Tôi đã làm hng mi chuyn. Tôi rt
mun gây n tượng vi các ngài “cu
hc vic đây nhưng rt cuc ch
làm ri tung c lên.
Ðó ngày đầu tiên tôi được làm mt
chân thc tp ca ông C. Tôi qu rt
may mn mi được v trí này. Ông
C mt người tiếng trong làng
phát trin phn mm. Cuc thi để
giành được chân hc vic này đúng
ny la.
Nhng người theo hc ông C
thường
s tr t
hành nhng người th
lành
ngh được đánh giá cao. Ðiu này
nghĩa được làm vic vi ông C
giá tr ràng.
I thought I was going to meet him
today, but instead a journeyman
named Jerry took me aside. He told
me that Mr. C always puts his
apprentices through an orientation
Tôi c ng hôm nay s được gp ông
C, nhưng tôi b “cu hc vic” Jerry
níu qua mt bên. bo ông C luôn
luôn yêu cu phn định hướng cho
người hc vic trong nhng ngày đầu.
while(!(success = try()));
www.codegym.vn / Page 03
during their first few days. He said this
orientation was to introduce
apprentices to the practices that Mr. C
insists we use, and to the level of
quality he expects from our code.
nói ông C nht quyết cho rng
phn định hướng này rt thiết thc vi
người hc vic, chất lượng
ngun mà ông mong đợi h.
This excited me greatly. It was an
opportunity to show them how good
a programmer I am. So I told Jerry I
couldn’t wait to start. He responded by
asking me to write a simple
program
for him. He wanted me to use the
Sieve of Eratosthenes to calculate
prime numbers. He told me to have
the program, including all unit tests,
ready for review just after lunch.
Tôi háo hc kinh khng. Ðây hội
để tôi cho h thy mình mt tay lập
trình gii c nào. Thế tôi bo Jerry
tôi không ch được na. đáp li
s háo hc ca tôi bng cách bo tôi
th viết mt chương trình đơn gin.
mun tôi dùng Sàng Eratosthenes
(Sieve) để tính các số nguyên tố.
còn bo tôi phi
chun b xong
chương trình bao gm trn b các
kiểm thử đơn vị để soát sau bui ăn
trưa.
This was great! I had almost four
hours to whip together a simple
program like the Sieve. I am
determined to do a really impressive
job. Listing 1 shows what I wrote. I
made sure it was well commented,
and neatly formatted.
Tht tuyt! Tôi gn 4 gi đồng h
để “xào nấu” mt chương trình đơn
gin như Sieve. Tôi quyết tâm làm mt
chương trình tht ấn tượng. Tôi đã
viết dn 1. Tôi nm chc
chương trìn
h được chú thích cn
thn và trình bày gọn gàng.
dẫn 1
/**
* This class generates prime numbers up to a user-specified maximum.
* The algorithm used is the Sieve of Eratosthenes. <p> Eratosthenes of
Cyrene, b.c.
* 276 BC, Cyrene, Libya; d.c.194 BC,Alexandria. He was the first man to
* calculate the circumference of the Earth, and was also known for working on
* calendars with leap years and running the library at Alexandri
a.</p> *
The
* algorithm is quite simple: Given an array of integers starting at 2, cross
* out all multiples of 2. Find the next uncrossed integer, and cross out all of
* its multiples. * Repeat until you have passed the square root of the maximum
* value.
* @authorAlphonse,
while(!(success = try()));
www.codegym.vn / Page 04
* @version 13 Feb 2002 atp
*/
import java.util.*;
public class GeneratePrimes {
/**
* @param maxValue is the generation limit.
*/
public static int[] generatePrimes(int maxValue)
{
if (maxValue >= 2) { // the only valid case
// declarations
int s = maxValue + 1; // size of array
boolean[] f = new boolean[s];
int i;
// initialize array to true.
for (i = 0; i < s; i++)
{
f[i] = true;
}
// get rid of known non-pr
imes.
f[0] = f[1] = false;
// sieve
int j;
for (i = 2; i < Math.sqrt(s) + 1; i++)
{
if (f[i]) { // if i is uncrossed, cross its multiples.
for (j = 2 * i; j < s; j += i)
f[j] = false; // multiple is not prime
}
}
// how many primes are there?
int count = 0;
for (i = 0; i < s; i++) {
if (f[i]) {
count++; // bump count.
}
}
int[] primes = new int[count];
// move the primes into the result.
for (i = 0, j = 0; i
< s; i++) {
if (f[i]) // if prime
while(!(success = try()));
www.codegym.vn / Page 05
{
primes[j++] = i;
}
}
return primes; // return the primes.
} else // maxValue < 2
{
return new int[0]; // return null array if bad input.
}
}
}
Then I wrote a unit test for
GeneratePrimes. It is shown in Listing
2. It uses the JUnit framework as Jerry
had instructed. It takes a statistical
approach; checking to see if the
generator can generate primes up to
0, 2, 3, and 100.
In the first case there should be no
primes. In the second there should be
one prime
, and it should be 2. In the
third there should be two primes and
they should be 2 and 3. In the last
case there should be 25 primes, the
last of which is 97.
If all these tests pass, then I assumed
that the generator was working. I
doubt this is foolproof, but I couldn’t
think of a reasonable scenario where
these tests would pass and yet the
function would fail.
Sau đó tôi viết mt kim th đơn v
cho GeneratePrimes. Xem
dn 2. Ðon này dùng khung làm
vic JUnit như Jerry đã
ớng dẫn.
tiếp cn kiu thống ; kim tra
xem cái “generator” th to ra các
s nguyên ti 0, 2, 3 và 100.
Trong trường hợp th nht hn
không số nguyên nào c. Trong
trường hp th hai phi mt s
nguyên phi s 2. Trường
hp th ba hai s nguyên chúng
s 2 3. Trường hp cui phi
25 s nguyên và s cui phi là 97.
Nếu các kim th đều đạt, thì tôi giả
định “generator” chy. Tôi e rng
khó th tin cy tuyt đối cách
trên, nhưng tôi không nghĩ ra đượ
c
mt kịch bản th xy ra nào
mt hàm sai nhưng các bước kim
th đúng.
Mã dn 2
import junit.framework.*;
import java.util.*;
public class TestGeneratePrimes extends TestCase {
public static void main(String args[]) {
junit.swingui.TestRunner.main(new
String[]{"TestGeneratePrimes"});
while(!(success = try()));
www.codegym.vn / Page 06
}
public TestGeneratePrimes(String name) {
super(name);
}
public void testPrimes() {
int[] nullArray = GeneratePrimes.generatePrimes(0);
assertEquals(nullArray.length, 0);
int[] minArray = GeneratePrimes.generatePrimes(2);
assertEquals(minArray.length, 1);
assertEquals(minArray[0], 2);
int[] threeArray = GeneratePrimes.generatePrimes(3);
assertEquals(threeArray.length, 2);
assertEquals(threeArray[0], 2);
asser
tEquals(threeArray[1], 3);
int[] centArray = GeneratePrimes.generatePrimes(100);
assertEquals(centArray.length, 25);
assertEquals(centArray[24], 97);
}
}
I got all this to work in about an hour.
Jerry didn't want to see me until after
lunch, so I spent the rest of my time
reading the Design Patterns book that
Jerry gave me.
After lunch I stopped by Jerry’s office,
and told him I was done with the
program. He looked up at me with a
funny grin on his face and said:
“G
ood, let's go check it out.”
Tôi làm vic này mt khong mt gi
đồng. Jerry không mun gp tôi trước
ba ăn trưa, bi thế, tôi dành trn b
thi gian còn li đọc cun Design
Patterns mà Jerry đưa cho.
Sau bui ăn trưa, tôi ghé văn phòng
ca Jerry cho biết tôi đã thc
hin xong chương trình. nhìn tôi
cười, hn nói: “Ðược lm, hãy xem
thử nó thế nào.”
He took me out into the lab and sat me
down in front of a workstation. He sat
next to me. He asked me to bring up
my program on this m
achine. So I
navigated to my laptop on the network
and brought up the source files.
Sau ba trưa, dn tôi vào phòng
máy cho tôi ngi trước mt máy.
ngi bên cnh tôi yêu cu tôi
đưa chương trình ca tôi vào máy
này. Thế tôi kết ni laptop vi mng
và chuyn mã ngun lên.
while(!(success = try()));
www.codegym.vn / Page 07
Jerry looked at the two source files for
about five minutes. Then he shook
his head and said: “You can’t show
something like this to Mr. C! If I let him
see this, he’d probably fire both of us.
He’s not a very patient man.”
Jerry xem xét hai ngun chng
năm phút ri lắc đầu bo: “Mày
không th đưa nhng cái này cho ông
C xem được! Nếu tao để ông y xem
my cái này, thì ông s sa thi c hai.
Ông y không phi người kiên
nhẫn đâu.”
I was startled, but managed to keep
my cool enough to ask:
“What’s
wrong with it?”
Jerry sighed. “Let's walk through this
together,” he said. “I’ll show you, point
by point, how Mr. C wants things
done.”
Tôi đánh thót mt cái nhưng c giữ
bình tĩnh hi gã: “Vy sai ch
nào?”
Jerry thở dài nói: “Ti mình s
lược qua đống này. Tao s hướng
dn chi tiết cho mày cách ông C
mun.”
“It seems pretty clear, he continued,
“that the main function wants to be
three separate functions. The first
initializes all the variables and sets up
the sieve
. The second actually
executes the sieve, the third loads
the sieved results into an integer
array.”
“Khá ràng”, tiếp tc, “rng
nên tách hàm main thành ba hàm
riêng biệt. Hàm th nht khởi tạo tt
c các biến thiết lp cái “sieve”.
Hàm th hai thc s thi hành cái
“sieve” hàm th ba tải kết qu ca
“sieve” vào mt dãy số nguyên.”
I could see what he meant. There
were three concepts which were
buried in that function. Still, I didn’t
see what he wanted me to do about
it.
He looked at me for a while, clearly
expecting me to do something. But
finally he heaved a sigh, shook his
head, and...
Tôi nhn ra được ý gã. ba khái
niệm chôn trong cái hàm đó. Tuy vy,
tôi không biết gã mun tôi phi làm gì.
nhìn tôi mt lúc, ràng đang
đợi xem tôi phn ng sao. Nhưng rt
cuc gã thở dài, lắc đầu và….
Thợ lành nghề #2 - Chế độ ăn kiêng tăng cường
and continued. “To expose these
three concepts more clearly, I want
tiếp tc. “Ð diễn tả
hơn ba khái
niệm này, tao mun mày tách chúng
while(!(success = try()));
www.codegym.vn / Page 08
you to extract them into three
separate methods. Also get rid of all
the unnecessary comments and pick
a better name for the class. When you
are done with that, make sure all the
tests still run.”
ra thành ba hàm riêng bit. Ðng thi
bỏ hết nhng chú thích không cần
thiết tìm mt cái tên khá hơn cho
lớp. Khi làm xong nhng th đó, mày
phi bo đảm nhng cái kim th
vn chy được.”
You can see what I did in Listing 3. I’ve
marked my changes in bold, just like
Martin Fowler does in his R
efactoring
book. I changed the name of the class
to a noun, got rid of all the comments
about Eratosthenes, and made three
methods out of the three concepts in
the generatePrimes function.
Các bn th thy nhng tôi đã
làm trong dn 3. Tôi in đậm để
đánh du nhng thay đổi, tương t
như Martin Fowler trình bày trong
cun Tái cấu trúc. Tôi đổi tên lp
thành mt danh t, b hết nhng chú
thích v Eratosthenes to ra ba
hàm tương ng vi ba khái nim trong
hàm generatePrimes.
Extr
acting the three functions forced
me to promote some of the variables
of the function to static fields of the
class. Jerry said that this made it
much clearer which variables are
local and which have wider influence.
Vic tách thành ba hàm bắt tôi phi
đưa mt s biến cc b ca hàm
thành thuộc tính ca lp. Jerry nói
cách này th hin hơn nhng biến
nào cục bộ biến hàm nào
ảnh hưởng rng hơn. dn 3.
PrimeGenerator.java, phiên bn 2
PrimeGenerator.java, phiên bản
2
/**
* This class Generates prime numbers up to a user specified maximum. The
* algorithm used is the Sieve of Eratosthenes. Given an array of integers
* starting at 2: Find the first uncrossed integer, and cross out all its
* multiples. Repeat until the first uncrossed integer exceeds the square root
* of the maximum value.
*/
import java.util.*;
public class PrimeGenerator {
private static int s;
private
static boolean[] f;
private static int[] primes;
while(!(success = try()));
www.codegym.vn / Page 09
public static int[] generatePrimes(int maxValue) {
if (maxValue < 2) {
return new int[0];
} else {
initializeSieve(maxValue);
sieve();
loadPrimes();
return primes; // return the primes
}
}
private static void loadPrimes() {
int i;
int j;
// how many primes are there?
int count = 0;
for (i = 0; i < s; i++) {
if (f[i]) {
count++; // bump count.
}
}
primes = new int[count];
// move the primes into the result for (i = 0,
j = 0; i < s; i++)
{
if (f[i]) // if prime
{
primes[j++] = i;
}
}
}
private static void sieve() {
int i;
int j;
for (i = 2; i < Math.sqrt(s) + 1; i++) {
while(!(success = try()));
www.codegym.vn / Page 10
if (f[i]) // if i is uncrossed, cross out its multiples.
{
for (j = 2 * i; j < s; j += i) {
f[j] = false; // multiple is not prime
}
}
}
}
private static void initializeSieve(int maxValue) {
// declarations
s = maxValue + 1; // size of array
f = new boolean[s];
int i;
// initialize array to true.
for (i = 0; i < s; i++) {
f[i] = true;
}
// get rid of known non-primes
f[0] = f[1] = false;
}
}
Jerry told me that this was a lit
tle
messy, so he took the keyboard and
showed me how to clean it up.
Listing 4 shows what he did. First he
got rid of the s variable in
initializeSieve and replaced it with
f.length. Then he changed the names
of the three functions to something he
said was a bit more expressive.
Finally he rearranged the innards of
initializeArrayOfIntegers (née
initializeSieve) to be a little nicer to
read. The tests all still ran.
Jerry bo tôi ngun này hơi lộn
xộn, nên giành ly b
àn phím ch
cho tôi cách dọn dẹp.
dn 4 minh ho nhng đã
làm. Đầu tiên vứt đi biến cc b s
trong initializeSieve thay thế
bng f.length. Sau đó đổi tên ca
ba hàm cho nghĩa hơn. Cui cùng
sp xếp li cái “bộ lòng”
initializeArrayOfIntegers (t
initializeSieve) để cho d đọc hơn mt
chút. Các cái kim th vn chy tt.
while(!(success = try()));
www.codegym.vn / Page 11
PrimeGenerator.java, phiên bn 3 (mt phn)
public class PrimeGenerator {
private static boolean[] f;
private static int[] result;
public static int[] generatePrimes(int maxValue) {
if (maxValue < 2) {
return new int[0];
} else {
initializeArrayOfIntegers(maxValue);
crossOutMultiples();
putUncrossedIntegersIntoResult();
return result;
}
}
private static void initializeArrayOfIntegers(int maxValue) {
f = new bool
ean[maxValue + 1];
f[0] = f[1] = false; //neither primes nor multiples.
for (int i = 2; i < f.length; i++) {
f[i] = true;
}
}
I had to admit, this was a bit cleaner.
I’d always thought it was a waste of
time to give functions long descriptive
names, but his changes really did
make the code more readable.
Next Jerry pointed at
crossOutMultiples. He said he thought
the if(f[i] == true) statements could be
made more readable. I thought about
it for a minute. The
intent of those
statements was to check to see if i
was uncrossed; so I changed the
name of f to unCrossed.
Tôi phi công nhn ngun này
ràng hơn mt chút. Trước gi tôi
nghĩ vic đặt tên dài tính t
cho hàm phung phí thi gi, nhưng
nhng điu chnh ca qu tht làm
cho mã ngun d đọc hơn.
Tiếp theo Jerry tr vào
crossOutMultiples nói nghĩ
th làm nhng lnh if(f[i] == true) d
đọc hơn na. Tôi nghĩ v đim này
chng mt phút. Ý định ca nhng
lnh này kim
tra xem liu i chưa
b loi; thế tôi đổi tên ca f thành
unCrossed.
while(!(success = try()));
www.codegym.vn / Page 12
during their first few days. He said this
orientation was to introduce
apprentices to the practices that Mr. C
insists we use, and to the level of
quality he expects from our code.
nói ông C nht quyết cho rng
phn định hướng này rt thiết thc vi
người hc vic, chất lượng
ngun mà ông mong đợi h.
This excited me greatly. It was an
opportunity to show them how good
a programmer I am. So I told Jerry I
couldn’t wait to start. He responded by
asking me to write a simple program
for him. He wanted me to use the
Sieve of Eratosthenes to calculate
prime numbers. He told me to have
the program, including all unit tests,
ready for review just after lunch.
Tôi háo hc kinh khng. Ðây hội
để tôi cho h thy mình mt tay lập
trình gii c nào. Thế tôi bo Jerry
tôi không ch được na. đáp li
s háo hc ca tôi bng cách bo tôi
th viết mt chương trình đơn gin.
mun tôi dùng Sàng Eratosthenes
(Sieve) để tính các số nguyên tố.
còn bo tôi phi chun b xong
chương trình bao gm trn b các
kiểm thử đơn vị để soát sau bui ăn
trưa.
This was great! I had almost four
hours to whip together a simple
program like the Sieve. I am
determined to do a really impressive
job. Listing 1 shows what I wrote. I
made sure it was well commented,
and neatly formatted.
Tht tuyt! Tôi gn 4 gi đồng h
để “xào nấu” mt chương trình đơn
gin như Sieve. Tôi quyết tâm làm mt
chương trình tht ấn tượng. Tôi đã
viết dn 1. Tôi nm chc
chương trình được chú thích cn
thn và trình bày gọn gàng.
dẫn 1
/**
* This class generates prime numbers up to a user-specified maximum.
* The algorithm used is the Sieve of Eratosthenes. &lt;p&gt; Eratosthenes of
Cyrene, b.c.
* 276 BC, Cyrene, Libya; d.c.194 BC,Alexandria. He was the first man to
* calculate the circumference of the Earth, and was also known for working on
* calendars with leap years and running the library at Alexandria.&lt;/p&gt; *
The
* algorithm is quite simpl
e: Given an array of integers starting at 2, cross
* out all multiples of 2. Find the next uncrossed integer, and cross out all of
* its multiples. * Repeat until you have passed the square root of the maximum
* value.
* @authorAlphonse,
Jerry said that this was better, but still
wasn’t pleased with it because it led to
double negatives like unCrossed[i] =
false. So he changed the name of the
array to isCrossed and changed the
sense of all the booleans. Then he ran
all the tests.
Jerry got rid of the initialization that
set isCrossed[0] and isCrossed[1] to
true. He said it was good enough to
just make sure that no part of the
function used the isCrossed array for
indexes less than 2. The tests all still
ran.
Jerry ex
tracted the inner loop of the
crossOutMultiples function and called
it crossOutMultiplesOf. He said that
statements like if (isCrossed[i] ==
false) were confusing so he created a
function called notCrossed and
changed the if statement to if
(notCrossed(i)). Then he ran the tests.
Then Jerry asked me what that square
root was all about. I spent a bit of time
writing a comment that tried to explain
why you only have to iterate up to the
square root of the array size.
I t
ried to emulate Jerry by extracting
the calculation into a function where I
could put the explanatory comment.
In writing the comment I realized that
the square root is the maximum prime
factor of any of the integers in the
array. So I chose that name for the
variables and functions that dealt with
it.
Finally, I made sure that the tests all
Jerry nói này được hơn nhưng
vn chưa hài lòng dn đến kh
năng ph định kép như unCrossed[i]
= false. Bi thế đổi tên mng thành
isCros
sed đổi ý nghĩa ca mi giá
tr lun lý. Sau đó chy mi kim
th.
Jerry xóa gán true cho
isCrossed[0] isCrossed[1]. nói
điu này đủ tt để đảm bo không
phn nào ca hàm dùng mng
isCrossed vi ch s nh hơn 2. Mi
kim th vn chy.
Jerry tách phn lp bên trong ca
hàm crossOutMultiples ra đặt tên
crossOutMultipleOf. bo rng các
lnh tương t như if (isCrossed[i] ==
false) d gây nhm ln, nên to
hàm tên notCrossed thay cm if
thành if (notCrossed(i))
. Kế tiếp
chy li my kim th.
Sau đó Jerry hi tôi ý nghĩa ca căn
bc hai tôi đã dùng. Tôi tn ít thi gi
viết chú thích cho do cn phi lp
li cho đến căn bc hai ca độ dài
mng.
Tôi c làm theo Jerry bng cách tách
phn tính toán thành mt hàm, tôi
th viết chú thích trong hàm này.
Trong khi viết chú thích tôi nhn ra
rng căn bc hai tha s nguyên t
ln nht ca bt k s nào trong
mng. Sau đó tôi chn tên cho các
hàm và biến x lý vn đề này
Cui cùng tôi bo đảm các kim th
while(!(success = try()));
www.codegym.vn / Page 13
* @version 13 Feb 2002 atp
*/
import java.util.*;
public class GeneratePrimes {
/**
* @param maxValue is the generation limit.
*/
public static int[] generatePrimes(int maxValue)
{
if (maxValue &gt;= 2) { // the only valid case
// declarations
int s = maxValue + 1; // size of array
boolean[] f = new boolean[s];
int i;
// initialize array to true.
for (i = 0; i &lt; s; i++)
{
f[i] = true;
}
// get rid of known non-pr
imes.
f[0] = f[1] = false;
// sieve
int j;
for (i = 2; i &lt; Math.sqrt(s) + 1; i++)
{
if (f[i]) { // if i is uncrossed, cross its multiples.
for (j = 2 * i; j &lt; s; j += i)
f[j] = false; // multiple is not prime
}
}
// how many primes are there?
int count = 0;
for (i = 0; i &lt; s; i++) {
if (f[i]) {
count++; // bump count.
}
}
int[] primes = new int[count];
// move the primes into the result.
for (i = 0, j = 0; i
&lt; s; i++) {
if (f[i]) // if prime
still ran. The result of all these
changes are shown in Listing 5.
vn chy. Kết qu ca các thay đổi
trong Mã dn 5.
PrimeGenerator.java phiên bn 4 (mt phn)
public class PrimeGenerator {
private static boolean[] isCrossed;
private static int[] result;
public static int[] generatePrimes(int maxValue) {
if (maxValue < 2) {
return new int[0];
} else {
initializeArrayOfIntegers(maxValue);
crossOutMultiples();
putUncrossedIn
tegersIntoResult();
return result;
}
}
private static void initializeArrayOfIntegers(int maxValue) {
isCrossed = new boolean[maxValue + 1];
for (int i = 2; i < isCrossed.length; i++) {
isCrossed[i] = false;
}
}
private static void crossOutMultiples() {
int maxPrimeFactor = calcMaxPrimeFactor();
for (int i = 2; i <= maxPrimeFactor; i++) {
if (notCrossed(i)) {
crossOutMultiplesOf(i);
}
}
}
while(!(success = try()));
www.codegym.vn / Page 14
{
primes[j++] = i;
}
}
return primes; // return the primes.
} else // maxValue &lt; 2
{
return new int[0]; // return null array if bad input.
}
}
}
Then I wrote a unit test for
GeneratePrimes. It is shown in Listing
2. It uses the JUnit framework as Jerry
had instructed. It takes a statistical
approach; checking to see if the
generator can generate primes up to
0, 2, 3, and 100.
In the first case there should be no
primes. In the second there should be
one prime, and it should be 2. In the
third there should be two primes and
they should be 2 and 3. In the last
case there should be 25 primes, the
last of which is 97.
If all these t
ests pass, then I assumed
that the generator was working. I
doubt this is foolproof, but I couldn’t
think of a reasonable scenario where
these tests would pass and yet the
function would fail.
Sau đó tôi viết mt kim th đơn v
cho GeneratePrimes. Xem
dn 2. Ðon này dùng khung làm
vic JUnit như Jerry đã hướng dẫn.
tiếp cn kiu thống ; kim tra
xem cái “generator” th to ra các
s nguyên ti 0, 2, 3 và 100.
Trong trường hợp th nht hn
không số nguyên nào c. Trong
trường hp th hai phi mt s
nguyên phi s 2. Trường
hp th ba hai s nguyên chúng
s 2 3. Trường hp cui phi
25 s nguyên và s cui phi là 97.
Nếu các kim th
đều đạt, thì tôi giả
định “generator” chy. Tôi e rng
khó th tin cy tuyt đối cách
trên, nhưng tôi không nghĩ ra được
mt kịch bản th xy ra nào
mt hàm sai nhưng các bước kim
th đúng.
Mã dn 2
import junit.framework.*;
import java.util.*;
public class TestGeneratePrimes extends TestCase {
public static void main(String args[]) {
junit.swingui.TestRunner.main(new
String[]{&quot;TestGeneratePrimes&quot;});
private static int calcMaxPrimeFactor() {
// We cross out all multiples of p, where p is prime.
// Thus, all crossed out multiples have p and q for
// factors. If p > sqrt of the size of the array, then
// q will never be greater than 1. Thus p is the
// largest prime factor in the array, and is also
// the iteration limit.
double maxPrimeFactor = Math.sqrt(isCrossed.length) + 1;
return (int) maxPrimeFact
or;
}
private static void crossOutMultiplesOf(int i) {
for (int multiple = 2 * i;
multiple < isCrossed.length;
multiple += i) {
isCrossed[multiple] = true;
}
}
private static boolean notCrossed(int i) {
return isCrossed[i] == false;
}
I was starting to get the hang of this
so I took a look at the putUncrossed-
IntegersIntoResult method. I saw that
this method had two parts.
The first counts the number of
uncrossed integers in the arra
y, and
creates the result array of that size.
The second moves the uncrossed
integers into the result array.
So, as you can see in Listing 6, I
extracted the first part into its own
function and did some miscellaneous
cleanup. The tests all still ran. Jerry
Tôi bt đầu nắm bắt được vn đề nên
lin xét hàm
putUncrossedIntegersIntoResult. Tôi
thy hàm này có hai phn.
Phn th nht đếm các s nguyên
không bị loại trong mng, to nên
mng kết qu (bng chiu dài ca
mng). Ph
n th hai di các s
nguyên không b loi vào dãy kết qu
này.
Bi thế, như bn thy trong dn 6,
tôi tách phn th nht ra để hình
thành hàm cho chính dn dp
while(!(success = try()));
www.codegym.vn / Page 15
}
public TestGeneratePrimes(String name) {
super(name);
}
public void testPrimes() {
int[] nullArray = GeneratePrimes.generatePrimes(0);
assertEquals(nullArray.length, 0);
int[] minArray = GeneratePrimes.generatePrimes(2);
assertEquals(minArray.length, 1);
assertEquals(minArray[0], 2);
int[] threeArray = GeneratePrimes.generatePrimes(3);
assertEquals(threeArray.length, 2);
assertEquals(threeArray[0], 2);
asser
tEquals(threeArray[1], 3);
int[] centArray = GeneratePrimes.generatePrimes(100);
assertEquals(centArray.length, 25);
assertEquals(centArray[24], 97);
}
}
I got all this to work in about an hour.
Jerry didn't want to see me until after
lunch, so I spent the rest of my time
reading the Design Patterns book that
Jerry gave me.
After lunch I stopped by Jerry’s office,
and told him I was done with the
program. He looked up at me with a
funny grin on his face and said:
“Good, let's go check it out.”
Tôi làm vic này mt khong mt gi
đồng. Jerry không mun gp tôi trước
ba ăn trưa, bi thế, tôi dành trn b
thi gian còn li đọc cun Design
Patterns mà Jerry đưa cho.
Sau bui ăn trưa, tôi ghé văn phòng
ca Jerry cho biết tôi đã thc
hin xong chương trình. nhìn tôi
cười, hn nói: “Ðược lm, hãy xem
thử nó thế nào.”
He took me out into the lab and sat me
down in front of a workstation. He sat
next to me. He asked me to bring up
my program on this machine. So I
navigated to my laptop on the network
and brought up the source files.
Sau ba trưa, dn tôi vào phòng
máy cho tôi ngi trước mt máy.
ngi bên cnh tôi yêu cu tôi
đưa chương trình ca tôi vào máy
này. Thế tôi kết ni laptop vi mng
và chuyn mã ngun lên.
was just barely nodding his head. Did
he actually like what I did?
li mt ít. Các kim th vn chy.
Jerry ch thoáng gt đầu. tht
s khoái nhng điu tôi đã thc hin
không?
Th lành ngh #3:Tính rõ ràng và cng tác
Next Jerry made pass over the whole
program, reading it from beginning to
end, rather like he was reading a
geometric proof. He told me that this
was a really important step. “So far”,
he said, “We’ve been refactoring
fragments. Now we want to see if the
w
hole program hangs together as a
readable whole.”
Sau đó Jerry đọc toàn b chương
trình, t đầu đến cui như th đang
đọc bài chng minh hình hc. bo
tôi đây mt bước hết sc quan
trng. “Ðến bước này, ti mình đã
thc hin tái cu trúc các phân
mnh ca chương trình. Bây gi ti
mình xem liu toàn b chương trình
gn kết vi nhau như mt tng th
đọc được.”
I asked: “Jerry, do you do this with
your own code too?”
Jerry scowled: “We work as a team
around here, so there is no code I cal
l
my own. Do you consider this code
yours now?”
“Not anymore.” I said, meekly. “You’ve
had a big influence on it.”
“We both have.” he said, “And that’s
the way that Mr. C likes it. He doesn’t
want any single person owning code.
But to answer your question: Yes. We
all practice this kind of refactoring and
code clean up around here. It’s Mr. C’s
way.”
Tôi hi: “Jerry, anh cũng làm như thế
vi chính mã ngun ca mình sao?”
Jerry quc mt lên nói: đây ti
tao làm vic v
i nhau theo nhóm nên
không cái nào ca riêng tao
hết. B mày cho rng cái này ca
riêng mày h?”
Tôi tr li nh nh: “Hết nghĩ như vy
ri, anh nh hưởng rt ln đến
ngun này.”
tr li: “C hai thng mình đều nh
hưởng đến nó, đây cách ông C
chung. Ông y không mun riêng
mt ai làm ch mã ngun hết đâu.
Câu tr li cho câu hi ca mày:
“Ðúng vy, đây ti tao thc hành tái
cu trúc dn rác. Đó cách làm
ca ông C.”
while(!(success = try()));
www.codegym.vn / Page 16
Jerry looked at the two source files for
about five minutes. Then he shook
his head and said: “You can’t show
something like this to Mr. C! If I let him
see this, he’d probably fire both of us.
He’s not a very patient man.”
Jerry xem xét hai ngun chng
năm phút ri lắc đầu bo: “Mày
không th đưa nhng cái này cho ông
C xem được! Nếu tao để ông y xem
my cái này, thì ông s sa thi c hai.
Ông y không phi người kiên
nhẫn đâu.”
I was startled, but managed to keep
my cool enough to ask: “What’s
wrong with it?”
Jerry sighed. “Let's walk through this
together,” he said. “I’ll show you, point
by point, how Mr. C wants things
done.”
Tôi đánh thót mt cái nhưng c giữ
bình tĩnh hi gã: “Vy sai ch
nào?”
Jerry thở dài nói: “Ti mình s
lược qua đống này. Tao s hướng
dn chi tiết cho mày cách ông C
mun.”
“It seems pretty clear, he continued,
“that the main function wants to be
three separate functions. The first
initializes all the variables and sets up
the sieve. The second actually
executes the sieve, the third loads
the sieved results into an integer
array.”
“Khá ràng”, tiếp tc, “rng
nên tách hàm main thành ba hàm
riêng biệt. Hàm th nht khởi tạo tt
c các biến thiết lp cái “sieve”.
Hàm th hai thc s thi hành cái
“sieve” hàm th ba tải kết qu ca
“sieve” vào mt dãy số nguyên.”
I could see what he meant. There
were three concepts which were
buried in that function. Still, I didn’t
see what he wanted me to do about it.
He looked at me for a while, clearly
expecting me to do something. But
finally he heaved a sigh, shook his
head, and...
Tôi nhn ra được ý gã. ba khái
niệm chôn trong cái hàm đó. Tuy vy,
tôi không biết gã mun tôi phi làm gì.
nhìn tôi mt lúc, ràng đang
đợi xem tôi phn ng sao. Nhưng rt
cuc gã thở dài, lắc đầu và….
Thợ lành nghề #2 - Chế độ ăn kiêng tăng cường
and continued. “To expose these
three concepts more clearly, I want
tiếp tc. “Ð diễn tả hơn ba khái
niệm này, tao mun mày tách chúng
Trong khi đọc lướt ngun, Jerry
nhn thy không thích cái tên
initializeArrayOfIntegers.
“What’s being initialized is not, in fact,
an array of integers;”, he said, “it’s an
array of booleans. But
initializeArrayOfBooleans is not an
improvement.
What we are really doing in this
method is uncrossing all the relevant
integers so that we can then cross out
the multiples.”
nói: “Cái được khi to đây thc
ra không phi mt mng s nguyên,
mt mng boolean. Nhưng
in
itializeArrayOfBooleans không phi
là mt ci tiến.
Ðiu chúng ta thc s mun làm
hàm này lit ra mt danh sách
các s nguyên phù hp để chúng
lên mt cái sàng, ri sau đó lc loi
ra các s không phi s nguyên t
(tc loi ra nhng bi s)”. (Do đó,
danh sách lúc đầu s không b gch
chéo, nhng s b loi s s b gch
chéo (crossed out)).
“Of course!” I said. So I grabbed the
keyboard and changed the name to
uncross- IntegersUpTo. I also realized
that I didn’t like the na
me isCrossed
for the array of booleans. So I
changed it to crossedOut. The tests all
still run. I was starting to enjoy this; but
Jerry showed no sign of approval.
Tôi tr li: “Tt nhiên ri!” Thế tôi
vớ lấy bàn phím sa tên ca hàm
đó thành uncrossIntegersUpTo. Tôi
cũng thy không khoái cái tên
isCrossed li dùng cho mt mng
boolean, nên tôi đổi thành
crossedOut. Các kim th vn chy.
Tôi bt đầu thy thích my cái trò này
nhưng Jerry vn chng h t v đồng
tình.
Then Jerry
turned to me and asked
me what I was smoking when I wrote
all that maxPrimeFactor stuff. (See
Listing 6.) At first I was taken aback.
But as I looked the code and
comments over I realized he had a
point. Yikes, I felt stupid! The square
root of the size of the array is not
Sau đó Jerry quay li hi tôi phi
tôi đã mơ màng theo khói thuc khi
viết cái m maxPrimeFactor. (Xem
dn 6). Thot đầu tôi hết sc ngỡ
ngàng nhưng khi xem li đon
các chú thích tôi nhn thy lý.
Eo ôi, tôi thy
mình tht ngu! Căn
bậc 2 ca chiu dài mt mng s
During the read-through, Jerry
realized that he didn’t like the name
initialize
ArrayOfIntegers.
while(!(success = try()));
www.codegym.vn / Page 17
you to extract them into three
separate methods. Also get rid of all
the unnecessary comments and pick
a better name for the class. When you
are done with that, make sure all the
tests still run.”
ra thành ba hàm riêng bit. Ðng thi
bỏ hết nhng chú thích không cần
thiết tìm mt cái tên khá hơn cho
lớp. Khi làm xong nhng th đó, mày
phi bo đảm nhng cái kim th
vn chy được.”
You can see what I did in Listing 3. I’ve
marked my changes in bold, just like
Martin Fowler does in his Refactoring
book. I changed the name of the class
to a noun, got rid of all the comments
about Eratosthenes, and made three
methods out of the three concepts in
the generatePrimes function.
Các bn th thy nhng tôi đã
làm trong dn 3. Tôi in đậm để
đánh du nhng thay đổi, tương t
như Martin Fowler trình bày trong
cun Tái cấu trúc. Tôi đổi tên lp
thành mt danh t, b hết nhng chú
thích v Eratosthenes to ra ba
hàm tương ng vi ba khái nim trong
hàm generatePrimes.
Extracting the three functions forced
me to promote some of the variables
of the function to static fields of the
class. Jerry said that this made it
much clearer which variables are
local and which have wider influence.
Vic tách thành ba hàm bắt tôi phi
đưa mt s biến cc b ca hàm
thành thuộc tính ca lp. Jerry nói
cách này th hin hơn nhng biến
nào cục bộ biến hàm nào
ảnh hưởng rng hơn. dn 3.
PrimeGenerator.java, phiên bn 2
PrimeGenerator.java, phiên bản 2
/**
* This class Generates prime numbers up to a user specified maximum. The
* algorithm used is the Sieve of Eratosthenes. Given an array of integers
* starting at 2: Find the first uncrossed integer, and cross out all its
* multiples. Repeat until the first uncrossed integer exceeds the square root
* of the maximum value.
*/
import java.util.*;
public class PrimeGenerator
{
private static int s;
private static boolean[] f;
private static int[] primes;
necessarily prime. That method did
not calculate the maximum prime
factor. The explanatory comment was
just wrong. So I sheepishly rewrote
the comment to better explain the
rationale behind the square root, and
renamed all the variables
appropriately. The tests all still ran.
không hn s nguyên. Hàm đó
không tính tha s nguyên t ln
nht. Phn chú gii sai bét, hết sc
ngượng ngùng tôi viết lại phn chú
thích để gii thích hơn cái căn bc
2 này dùng để làm đổi tên b
iến,
hàm cho thích hợp. Các kim th vn
chy.
dẫn 6. TestGeneratePrimes.java (mt phn)
public class TestGeneratePrimes {
private static int calcMaxPrimeFactor() {
// We cross out all multiples of p, where p is prime.
// Thus, all crossed out multiples have p and q for factors.
// If p &gt; sqrt of the size of the array, then q will never
// be greater than 1. Thus p is the largest prime factor
// in the array,
and is also the iteration limit.
double maxPrimeFactor = Math.sqrt(isCrossed.length) + 1;
return (int) maxPrimeFactor;
}
}
“What the devil is that +1 doing in
there?” Jerry barked at me.
I gulped, looked at the code, and
finally said: “I was afraid that a
fractional square root would convert
to an integer that was one too small to
serve as the iteration limit.”
“So you’re going to litter the code with
extra increments just because you
are paranoid?” he aske
d. “That’s
silly, get rid of the increment and run
“dùng +1 đây làm quái vy?” Jerry
tru tréo lên.
Tôi nuốt ực mt cái, xem li đon
cui cùng tôi phát biu: “Tôi ngi
khi ch ly phần nguyên ca căn bc
2, thì phn thp phân ca căn bc 2
đó b mt đi, do đó vòng lp th b
thiếu.”
bèn hi: “Cho nên mày xả rác
trong đon vi phần “+1” bi
mày b hoảng? Như thế thì ngc quá,
while(!(success = try()));
www.codegym.vn / Page 18
public static int[] generatePrimes(int maxValue) {
if (maxValue < 2) {
return new int[0];
} else {
initializeSieve(maxValue);
sieve();
loadPrimes();
return primes; // return the primes
}
}
private static void loadPrimes() {
int i;
int j;
// how many primes are there?
int count = 0;
for (i = 0; i < s; i++) {
if (f[i]) {
count++; // bump count.
}
}
primes = new int[count];
// move the primes into the result for (i = 0,
j = 0; i < s; i++)
{
if (f[i]) // if prime
{
primes[j++] = i;
}
}
}
private static void sieve() {
int i;
int j;
for (i = 2; i < Math.sqrt(s) + 1; i++) {
the tests.”
I did, and the tests all ran. I thought
about this for a minute, because it
made me nervous. But I decided that
maybe the true iteration limit was the
largest prime less than or equal to the
square root of the size of the array.
That last change makes me pretty
nervous.” I said to Jerry. “I understand
the rationale behind the square root,
but I’ve got a nagging feeling that
there may be some corner cases that
aren’t being covered.”
dp ngay cái trò gia tăng “+1 đó
chy kim th li đi.”
Tôi làm như thế toàn b các kim
th đều vn chy tt. Tôi nghĩ li phn
này mt lúc làm tôi lo lng. Thế
nhưng tôi quyết định th gii hn
lp li thc s chính s “tha s
nguyên t ln nht” “tha s
nguyên t đó nh hơn hoc bng căn
bc 2 chiu dài ca mng.
“Phn thay đổi va ri làm tôi khá bi
ri”. Tôi nói vi Jerry. “Tôi hiu ngun
gc đằng sau cái căn bc 2, nhưng tôi
cm thy không yên, biết đâu
trường hp “biên” nào đó chưa bao
quát hết.”
OK,” he grumbled. “So write another
test that checks that.”
“I suppose I could check that there are
no multiples in any of the prime lists
between 2 and 500.”
“OK, if it’ll make you feel better, try
that,” he said. He was clearly
becoming impatient.
So I wrote the testExhaustive function
shown in Listing 8. The new test
passed, and my fears were allayed.
Then Jerry relented a bit. “It’s always
good to know why something works,”
said Jerry. “and it’s even better when
you
show you are right with a test.”
lm bm “OK, vy thì viết mt cái
kim th khác để kim tra chuyn đó
đi.”
“Tôi nghĩ tôi th kim tra xem trong
các danh sách s nguyên t 2 đến
500 không có trường hp trên”.
“OK, nếu làm cho mày cm thy d
chu hơn, thì th đi.” nói. ràng
là gã bt đầu tr nên mt kiên nhn.
Thế tôi viết hàm testExhaustive như
trong dn 8. Phn kim th mi
này chy đúng ni lo s ca tôi
lng xung.
Jerry du xung mt chút. nói:
“Biết đ
ược do ti sao mt cái đó
chy được luôn luôn mt điu tt;
li càng tt hơn khi kim chng
while(!(success = try()));
www.codegym.vn / Page 19
if (f[i]) // if i is uncrossed, cross out its multiples.
{
for (j = 2 * i; j < s; j += i) {
f[j] = false; // multiple is not prime
}
}
}
}
private static void initializeSieve(int maxValue) {
// declarations
s = maxValue + 1; // size of array
f = new boolean[s];
int i;
// initialize array to true.
for (i = 0; i < s; i++) {
f[i] = true;
}
// get rid of known non-primes
f[0] = f[1] = false;
}
}
Jerry told me that this was a little
messy, so he took the keyboard and
showed me how to clean it up.
Listing 4 shows what he did. First he
got rid of the s variable in
initializeSieve and replaced it with
f.length. Then he changed the names
of the three functions to something he
said was a bit more expressive.
Finally he rearranged the innards of
initializeArrayOfIntegers (née
initializeSieve) to be a little nicer to
read. The tests all still ran.
Jerry bo tôi ngun này hơi lộn
xộn, nên giành ly bàn phím ch
cho tôi cách dọn dẹp.
dn 4 minh ho nhng đã
làm. Đầu tiên vứt đi biến cc b s
trong initializeSieve thay thế
bng f.length. Sau đó đổi tên ca
ba hàm cho nghĩa hơn. Cui cùng
sp xếp li cái “bộ lòng”
initializeArrayOfIntegers (t
initializeSieve) để cho d đọc hơn mt
chút. Các cái kim th vn chy tt.
through all the code and tests (shown
in listings 7 and 8). He sat back,
thinking for a minute, and said: “OK, I
think we’re done. The code looks
reasonably clean. I’ll show it to Mr. C.”
Then he looked me dead in the eye
and said: “Remember this. From now
on when you write a module, get help
with it and keep it clean. If you hand in
anything below those standards you
won’t last long here.”
And with that, he strode off.
được mày đúng bng kim th.”
Sau đó Jerry qua trn
b
ngun các cái kim th mt ln
na (xem dn 7 8). ngã
người ra suy nghĩ chng mt phút
ri nói: Được ri, tao nghĩ ti mình
đã làm xong. ngun này xem ra đủ
ràng (clean) ri đó. Tao s đưa cho
ông C xem.”
Thế ri nhìn tôi, lnh lùng nói:
“Phi nh, t nay v sau khi mày viết
mt phn nào đó, nên tìm s giúp đỡ
nh gi cho ngun ràng.
Nếu mày nhúng tay vào nhng th
dưới tiêu chun này, thì không “th
được đây đâu.”
ro bước.
Mã dn 7. PrimeGenerator.java
(cui cùng)
/**
* This class generates prime numbers up to a user specified maximum. The
* algorithm used is the Sieve of Eratosthenes. Given an array of * integers
* starting at 2: Find the first uncrossed integer, and cross out all its
* multiples. Repeat until there are no more multiples in the array.
*/
public class PrimeGenerator {
private static boolean[] crossedOut;
private static int[] result;
publ
ic static int[] generatePrimes(int maxValue) {
if (maxValue &lt; 2) {
return new int[0];
} else {
uncrossIntegersUpTo(maxValue);
crossOutMultiples();
Then Jerry scrolled one more time
while(!(success = try()));
www.codegym.vn / Page 20
putUncrossedIntegersIntoResult();
return result;
}
}
private static void uncrossIntegersUpTo(int maxValue) {
crossedOut = new boolean[maxValue + 1];
for (int i = 2; i &lt; crossedOut.length; i++) {
crossedOut[i] = false;
}
}
private static void crossOutMultiples() {
int limit = determineIterationLimit();
for (int i = 2; i &lt;= limit; i++) {
if (notCrossed(i)) {
crossOutMultiplesOf(i);
}
}
}
private static int dete
rmineIterationLimit() {
// Every multiple in the array has a prime factor that is
// less than or equal to the sqrt of the array size, so we
// don't have to cross out multiples of numbers larger than that root.
double iterationLimit = Math.sqrt(crossedOut.length);
return (int) iterationLimit;
}
private static void crossOutMultiplesOf(int i) {
for (int multiple = 2 * i; multiple &lt; crossedOut.length; mu
ltiple += i) {
crossedOut[multiple] = true;
}
}
private static boolean notCrossed(int i) {
while(!(success = try()));
www.codegym.vn / Page 21
return crossedOut[i] == false;
}
private static void putUncrossedIntegersIntoResult() {
result = new int[numberOfUncrossedIntegers()];
for (int j = 0, i = 2; i &lt; crossedOut.length; i++) {
if (notCrossed(i)) {
result[j++] = i;
}
}
}
private static int numberOfUncrossedIntegers() {
int count = 0;
for (int i = 2; i &lt; crossedOut.length; i++) {
if (notCrossed(i)) {
count++;
}
}
return count;
}
}
Mã dẫn 8. TestGenerat
ePrimes.java (cui cùng)
import junit.framework.*;
public class TestGeneratePrimes extends TestCase {
public static void main(String args[]) {
junit.swingui.TestRunner.main(
new String[]{&quot;TestGeneratePrimes&quot;});
}
public TestGeneratePrimes(String name) {
super(name);
}
while(!(success = try()));
www.codegym.vn / Page 22
still ran. The result of all these
changes are shown in Listing 5.
vn chy. Kết qu ca các thay đổi
trong Mã dn 5.
PrimeGenerator.java phiên bn 4 (mt phn)
public class PrimeGenerator {
private static boolean[] isCrossed;
private static int[] result;
public static int[] generatePrimes(int maxValue) {
if (maxValue < 2) {
return new int[0];
} else {
initializeArrayOfIntegers(maxValue);
crossOutMultiples();
putUncrossedIntegersIntoResult();
return result;
}
}
private static void initializeArrayOfIntegers(int maxValue) {
isCro
ssed = new boolean[maxValue + 1];
for (int i = 2; i < isCrossed.length; i++) {
isCrossed[i] = false;
}
}
private static void crossOutMultiples() {
int maxPrimeFactor = calcMaxPrimeFactor();
for (int i = 2; i <= maxPrimeFactor; i++) {
if (notCrossed(i)) {
crossOutMultiplesOf(i);
}
}
}
public void testPrimes() {
int[] nullArray = PrimeGenerator.generatePrimes(0);
assertEquals(nullArray.length, 0);
int[] minArray = PrimeGenerator.generatePrimes(2);
assertEquals(minArray.length, 1);
assertEquals(minArray[0], 2);
int[] threeArray = PrimeGenerator.generatePrimes(3);
assertEquals(threeArray.length, 2);
assertEquals(threeArray[0], 2);
assertEquals(threeArray[1], 3);
int[] centArray = PrimeGener
ator.generatePrimes(100);
assertEquals(centArray.length, 25);
assertEquals(centArray[24], 97);
}
public void testExhaustive() {
for (int i = 2; i &lt; 500; i++) {
verifyPrimeList(PrimeGenerator.generatePrimes(i));
}
}
private void verifyPrimeList(int[] list) {
for (int i = 0; i &lt; list.length; i++) {
verifyPrime(list[i]);
}
}
private void verifyPrime(int n) {
for (int factor = 2; factor &lt; n; factor++) {
asse
rt (n % factor != 0);
}
}
}
What a disaster! I thought that my
original solution had been top-notch.
Qu tai ho! Tôi c ng gii pháp
nguyên thy ca tôi thượng hạng.
while(!(success = try()));
www.codegym.vn / Page 23
private static int calcMaxPrimeFactor() {
// We cross out all multiples of p, where p is prime.
// Thus, all crossed out multiples have p and q for
// factors. If p > sqrt of the size of the array, then
// q will never be greater than 1. Thus p is the
// largest prime factor in the array, and is also
// the iteration limit.
double maxPrimeFactor = Math.sqrt(isCrossed.length) + 1;
return (int) maxPrimeFact
or;
}
private static void crossOutMultiplesOf(int i) {
for (int multiple = 2 * i;
multiple < isCrossed.length;
multiple += i) {
isCrossed[multiple] = true;
}
}
private static boolean notCrossed(int i) {
return isCrossed[i] == false;
}
I was starting to get the hang of this
so I took a look at the putUncrossed-
IntegersIntoResult method. I saw that
this method had two parts.
The first counts the number of
uncrossed integers in the array, and
creates the result array of that size.
The second moves the uncrossed
integers into the result array.
So, as you can see in Listing 6, I
extracted the first part into its own
function and did some miscellaneous
cleanup. The tests all still ran. Jerry
Tôi bt đầu nắm bắt được vn đề nên
lin xét hàm
putUncrossedIntegersIntoResult. Tôi
thy hàm này có hai phn.
Phn th nht đếm các s nguyên
không bị loại trong mng, to nên
mng kết qu (bng chiu dài ca
mng). Phn th hai di các s
nguyên không b loi vào dãy kết qu
này.
Bi thế, như bn thy trong dn 6,
tôi tách phn th nht ra để hình
thành hàm cho chính dn dp
In some ways I still feel that way. I had
tried to show off my brilliance, but I
guess Mr. C values collaboration and
clarity more than individual brilliance.
Chút đó tôi vn còn cm thy như
vy. Tôi c phô trương tài năng ca
mình nhưng tôi đoán ông C đánh
giá cao sự cộng tác tính minh
bạch hơn tài năng nhân.
I had to admit that the program reads
much better than it did at the start. It
also works a bit better. I was pretty
pleased with the outcome. Also, in
spite of Jerry’s gruf
f attitude, it had
been fun working with him. I had
learned a lot.
Tôi phi thú nhn rng chương trình
này d xem hơn lúc khi đầu. li
làm vic tt hơn mt na. Tôi khá
hài lòng vi kết quả và, mc Jerry
thái độ cộc cằn, nhưng làm vic
vi tôi cũng thy vui. Tôi hc hi
được rt nhiu
Still, I was pretty discouraged with my
performance. I don’t think the folks
here are going to like me very much.
I’m not sure they’ll ever think I’m good
enough for them. This is going to be a
lot ha
rder than I thought.
Du vy, tôi thy hơi chùn bước vi
chính hiu sut ca mình. Tôi không
dám nghĩ mấy tay đây s khoái
tôi cho lm. Tôi cũng không dám chc
đến bao bao gi h đánh giá tôi đủ
“ngon”. S th s khó khăn hơn tôi
nghĩ nhiu lm.
Thợ lành nghề #4 - Bài kiểm tra tính kiên nhẫn
12 July 2002
Dear Diary,
Last night I stared out the window for
hours watching the stars drifting
through the night sky. I felt conflicted
about the work I did with Jerry
yesterday. I l
earned a lot from working
with Jerry on the prime generator, but I
don’t think I impressed him very much.
And, frankly, I wasn’t all that
impressed with him. He spent a lot of
time polishing a piece of code that
worked just fine.
Ngày 12 tháng 7 năm 2002
Nht ký thân yêu,
Ti qua tôi ngi ta vào ca s hàng
gi, nhìn các sao trôi dạt trên bu
tri đêm. Tôi thy vic làm ca tôi
Jerry hôm qua nhiu xung đột. Tôi
hc hi rt nhiu trong khi làm vic vi
Jerry vi vn đề to s nguy
ên t,
nhưng tôi không tin tôi gây n tượng
vi gã. Và, thật tình nói, tôi
cũng không n cho lm. Tht ra,
tn khá nhiu thi gian mài dũa các
đon cho nhng đon này làm
vic ngon lành.
while(!(success = try()));
www.codegym.vn / Page 24
Today Jerry came to me with a new
exercise. He asked me to write a
program that calculates the prime
factors of an integer. He said he’d
work with me from the start. So the
two of us sat down and began to
program.
Hôm nay Jerry đến gp tôi vi mt bài
tp mi. yêu cu tôi viết mt
chương trình tính tha s nguyên t
ca s nguyên. cho biết s làm
vic vi tôi ngay t đầu nên hai chúng
tôi ngi xung và bt đầu lp trình.
I was pretty sure I knew how to do
this. We had written the prime
ge
nerator yesterday. Finding prime
factors is just a matter of walking
through a list of primes and seeing if
any are factors of the given integer.
So I grabbed the keyboard and began
to write code. After about half an hour
of writing and testing I had produced
the following.
Tôi tin chc tôi biết cách làm. Hôm
qua chúng tôi đã viết chương trình to
s nguyên t. tìm các tha s
nguyên t ch vn đề đi xuyên qua
danh sách các s nguyên t xét th
tha s nào t các s nguyên đã
đ
nh.
Thế nên tôi vi ly bàn phím bt
đầu viết mã. Khong na gi sau khi
viết và kim tra, tôi làm được như sau:
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
public class PrimeFactorizer {
public static void main(String[] args) {
int[] factors = findFactors(Integer.parseInt(args[0]));
for (int i = 0; i &amp;amp;lt; factors.length; i++) {
System.out.println(factors[i]);
}
}
public static i
nt[] findFactors(int multiple) {
List factors = new LinkedList();
int[] primes = PrimeGenerator.generatePrimes((int) Math.sqrt(multiple));
for (int i = 0; i &amp;amp;lt; primes.length; i++) {
for (; multiple % primes[i] == 0; multiple /= primes[i]) {
while(!(success = try()));
www.codegym.vn / Page 25
Trong khi đọc lướt ngun, Jerry
nhn thy không thích cái tên
initializeArrayOfIntegers.
“What’s being initialized is not, in fact,
an array of integers;”, he said, “it’s an
array of booleans. But
initializeArrayOfBooleans is not an
improvement.
What we are really doing in this
method is uncrossing all the relevant
integers so that we can then cross out
the multiples.”
nói: “Cái được khi to đây thc
ra không phi mt mng s nguyên,
mt mng boolean. Nhưng
initializeArrayOfBooleans không phi
là mt ci tiến.
Ðiu chúng ta thc s mun làm
hàm này lit ra mt danh sách
các s nguyên phù hp để chúng
lên mt cái sàng, ri sau đó lc loi
ra các s không phi s nguyên t
(tc loi ra nhng bi s)”. (Do đó,
danh sách lúc đầu s không b gch
chéo, nhng s b loi s s b gch
chéo (crossed out)).
“Of course!” I said. So I grabbed the
keyboard and changed the name to
uncross- IntegersUpTo. I also realized
that I didn’t like the name isCrossed
for the array of booleans. So I
changed it to crossedOut. The tests all
still run. I was starting to enjoy this; but
Jerry showed no sign of approval.
Tôi tr li: “Tt nhiên ri!” Thế tôi
vớ lấy bàn phím sa tên ca hàm
đó thành uncrossIntegersUpTo. Tôi
cũng thy không khoái cái tên
isCrossed li dùng cho mt mng
boolean, nên tôi đổi thành
crossedOut. Các kim th vn chy.
Tôi bt đầu thy thích my cái trò này
nhưng Jerry vn chng h t v đồng
tình.
Then Jerry turned to me and asked
me what I was smoking when I wrote
all that maxPrimeFactor stuff. (See
Listing 6.) At first I was taken aback.
But as I looked the code and
comments over I realized he had a
point. Yikes, I felt stupid! The square
root of the size of the array is not
Sau đó Jerry quay li hi tôi phi
tôi đã mơ màng theo khói thuc khi
viết cái m maxPrimeFactor. (Xem
dn 6). Thot đầu tôi hết sc ngỡ
ngàng nhưng khi xem li đon
các chú thích tôi nhn thy lý.
Eo ôi, tôi thy mình tht ngu! Căn
bậc 2 ca chiu dài mt mng s
factors.add(new Integer(primes[i]));
}
}
return createFactorArray(factors);
}
private static int[] createFactorArray(List factors) {
int factorArray[] = new int[factors.size()];
int j = 0;
for (Iterator fi = factors.iterator(); fi.hasNext();) {
Integer factor = (Integer) fi.next();
factorArray[j++] = factor.intValue();
}
return factorArray;
}
}
I tested the program by running the
main program with several different
argument
s. They all seemed to work.
Running it with 100 gave me 2, 2, 5,
and 5. Running it with 32767 gave me
7, 31, and 151. Running it with 32768
gave me fifteen twos.
Tôi kim tra chương trình bng cách
chy vi nhiu tham số khác nhau.
Mi th dường như n tho. Chy
chương trình vi giá tr tham s 100
cho tôi kết qu 2, 2, 5 5. Chy
vi 32767 cho tôi 7, 31 151. Chy
vi 32768 cho tôi 15 s 2.
Jerry just sat there and watched me.
He didn’t say a word. This made me
nervous, but I kept on
massaging and
testing the code until I was happy with
it. Then I started writing the unit tests.
Jerry ngi nhìn tôi. chng nói na
li. Ðiu này làm tôi hơi hong nhưng
tôi tiếp tc nắn bóp th nghim
ngun cho đến lúc tôi hài lòng. Sau
đó, tôi bt đầu viết phn kim th đơn
v.
“What are you doing?” asked Jerry.
“The program works, so I’m writing the
unit tests.” I replied.
“Why do you need unit tests if the
program already works?” he said?
Jerry hi: “Mày
làm gì vy?”
“Chương trình chy nên tôi đang viết
các kim th đơn v.” Tôi đáp li.
“Nếu chương trình đã chy thì vic
mày cn kim th đơn v?” hi
while(!(success = try()));
www.codegym.vn / Page 26
necessarily prime. That method did
not calculate the maximum prime
factor. The explanatory comment was
just wrong. So I sheepishly rewrote
the comment to better explain the
rationale behind the square root, and
renamed all the variables
appropriately. The tests all still ran.
không hn s nguyên. Hàm đó
không tính tha s nguyên t ln
nht. Phn chú gii sai bét, hết sc
ngượng ngùng tôi viết lại phn chú
thích để gii thích hơn cái căn bc
2 này dùng để làm đổi tên biến,
hàm cho thích hợp. Các kim th vn
chy.
dẫn 6. TestGeneratePrimes.java (mt phn)
public class TestGeneratePrimes {
private static int calcMaxPrimeFactor() {
// We cross out all multiples of p, where p is prime.
// Thus, all crossed out multiples have p and q for factors.
// If p &gt; sqrt of the size of the array, then q will never
// be greater than 1. Thus p is the largest prime factor
// in the array, and is also the iteration limit.
doub
le maxPrimeFactor = Math.sqrt(isCrossed.length) + 1;
return (int) maxPrimeFactor;
}
}
“What the devil is that +1 doing in
there?” Jerry barked at me.
I gulped, looked at the code, and
finally said: “I was afraid that a
fractional square root would convert
to an integer that was one too small to
serve as the iteration limit.”
“So you’re going to litter the code with
extra increments just because you
are paranoid?” he asked. “That’s
silly, get rid of the increment and run
“dùng +1 đây làm quái vy?” Jerry
tru tréo lên.
Tôi nuốt ực mt cái, xem li đon
cui cùng tôi phát biu: “Tôi ngi
khi ch ly phần nguyên ca căn bc
2, thì phn thp phân ca căn bc 2
đó b mt đi, do đó vòng lp th b
thiếu.”
bèn hi: “Cho nên mày xả rác
trong đon vi phần “+1” bi
mày b hoảng? Như thế thì ngc quá,
I hadn’t thought of it that way. I just
knew that you were supposed to write
unit tests. I ventured a guess: “So that
other programmers can see that it
works?”
Jerry looked at me for about thirty
seconds. Then he shook his head and
said: “What are they teaching you
guys in school nowadays?”
tiếp.
Tôi không nghĩ đến đim này. Tôi ch
biết theo thông l cn phi viết kim
th đơn v. Tôi liu lĩnh đoán mò: “Ð
các lp trình viên khác biết được
chương trình đó chy?”
Jerry nhìn tôi kho
ng 30 giây ri lc
đầu nói: “Thi bui này h dy d
ti mày cái gì trường vy?”
I started to answer, but he stopped me
with a look.
“OK”, he said, “delete what you’ve
done. I’ll show you how we do things
around here.”
I wasn’t prepared for this. He wanted
me to delete what I had just spent
thirty minutes creating. I just sat there
in disbelief.
Finally, Jerry said: “Go ahead, delete
it.”
“But it works.” I said.
“So what?” Said Jerry.
I was starting to get testy. “T
here’s
nothing wrong with it!” I asserted.
“Really.” he grumbled ; and he
grabbed the keyboard and deleted my
code.
Tôi cng lưỡi không tr li được
nhưng ngăn tôi li bng mt cái
nhìn.
“OK”, nói, “xoá hết nhng th mày
đã làm đi. Tao ch cho mày cách ti
tao làm đây.”
Tôi qu không chun b cho tình thế
như vy. mun tôi xoá nhng tôi
đã to ra trong ba mươi phút qua. Tôi
ch ngi yên, hoài nghi nhng mình
va nghe.
Cui cùng Jerry nói: “Xoá đi.”
Tôi tr li: “Nhưng
chương trình đó
chy mà.”
“Thì sao?” Jerry đáp li.
Tôi cng c cãi. Tôi khng khái:
“Chương trình này chng sai
hết!”
“Thc vy h?” lm bm v ly
bàn phím, ri xoá hết ngun ca
tôi.
while(!(success = try()));
www.codegym.vn / Page 27
I was dumbfounded. No, I was
furious. He had just reached over
and deleted my work. For a minute I
stopped caring about the prestige of
being an apprentice of Mr. C.
What good was that apprenticeship if it
meant I had to work with brutes like
Jerry? These, and other less
complimentary, thoughts raced
behind my eyes as I glared at him.
Tôi chết lng. Không phi, tôi điên
tiết lên. mi va chm qua
xoá hết đồ ca tôi. Trong phút chc y
tôi chng còn thiết đến ưu thế
đư
c làm mt tay hc vic cho ông C
na.
Hc vic phi đụng đến nhng k
tàn bo như Jerry thì còn hay ho
na? Vi ý nghĩ như thế nhng ý
nghĩ còn kém phn tưởng thưởng
khác nhy ra trong đầu khi tôi nhìn
chm chp.
“Ah. I see that upsets you.” Jerry said
calmly.
I sputtered, but couldn’t say anything
intelligent.
“Look.” Jerry said, clearly trying to
calm me down. “Don’t become vested
in your code. This was just thirty
minutes worth of work. It’s not that big
a deal. You need to be rea
dy to throw
away a lot more code than that if you
want to become any kind of a
programmer. Often the best thing you
can do with a batch of code is throw it
out.”
“À, tao thy mày ni đ ri đó.” Jerry
nói mt cách đim tĩnh.
Tôi lp bp nhưng chng tht được
ra hn (thông minh).
“Này.” Jerry nói, ràng đang c làm
du tôi xung. “Ðng bám rt
ngun ca mày quá như vy. Ch
ba mươi phút làm vic thôi, chng
phi cái ghê gm đâu. Mày phi
chun b tinh thn vt b thêm c
đống
ngun na nếu mày mun
tr thành mt th lp trình viên đó.
Vt b được hàng đống ngun
thường điu tt nht mày nên
làm.”
“But that’s such a waste!” I blurted.
“Do you think the value of a program
is in the code?” he asked. “It’s not.
The value of a program is in your
head.”
Tôi but ming: “Nhưng làm như thế
thì rt phí!”
hi li: “B mày nghĩ giá tr ca
chương trình nm trong ngun
sao? Không phi vy. Giá tr ca mt
while(!(success = try()));
www.codegym.vn / Page 28
He looked at me for a second, and
then went on. “Have you ever
accidentally deleted something you
were working on? Something that took
a few days of
effort
?”
“Once, at school.” I said. “A disk
crashed and the latest backup was
two days old.
He winced and nodded knowingly.
Then he asked: “How long did it take
you to recreate what you had lost?”
“I was pretty familiar with it, so it only
took me about half a day to recreate
it.”
“So you didn’t really lose two days
worth of work.
chương trình nm trong cái đầu ca
mày đó.”
nhìn tôi chng mt giây ri tiếp
tc. “Có bao gi mày l tay xoá cái
đó đang làm chưa? Cái đó mày
phi mt vài ngày c gng để làm?”
“Có mt ln, trường”. Tôi nói Cái
đĩa b hng bn lưu tr thì cách đó
hai ngày ri.”
cau mày gt đầu biu l s thông
cm ri hi: “Mày mt bao lâu để làm
li nhng cái đã b mt?”
“Tôi nm khá nhng cái b mt nên
ch mt có na ngày để làm li.”
“Ra thế mày tht s chng mt khi
lượng công
vic ca hai ngày.”
I didn’t care for his logic. I couldn’t
refute it, but I didn’t like it. It felt like I
had lost two days worth of work!
“Did you notice whether the new code
was better or worse than the code you
lost?” he asked.
“Oh, it was much better.” I said,
regretting my words the instant I said
them. “I was able to use a much better
structure the second time.”
He smiled. “So for an extra 25% effort,
you wound up with a better solution.”
Tôi chng màng đến cái l
ý lun ca
gã. Tôi không bác b được nhưng tôi
không khoái cái lun đó. Ch đơn
gin tôi cm thy b mt mt khi
lượng hai ngày làm vic!
hi tiếp: “Mày để ý liu phn
làm li tt hay t hơn phn
mày mt không?”
, tt hơn nhiu.” Tôi nói, hi tiếc
ngay giây phút tôi tht ra. “Ln th
hai tôi th dùng mt cu trúc tt
hơn nhiu.”
cười. “Thế thì c thêm 25%, mày
đưa đến mt gii pháp tt hơn.”
while(!(success = try()));
www.codegym.vn / Page 29
putUncrossedIntegersIntoResult();
return result;
}
}
private static void uncrossIntegersUpTo(int maxValue) {
crossedOut = new boolean[maxValue + 1];
for (int i = 2; i &lt; crossedOut.length; i++) {
crossedOut[i] = false;
}
}
private static void crossOutMultiples() {
int limit = determineIterationLimit();
for (int i = 2; i &lt;= limit; i++) {
if (notCrossed(i)) {
crossOutMultiplesOf(i);
}
}
}
private static int dete
rmineIterationLimit() {
// Every multiple in the array has a prime factor that is
// less than or equal to the sqrt of the array size, so we
// don't have to cross out multiples of numbers larger than that root.
double iterationLimit = Math.sqrt(crossedOut.length);
return (int) iterationLimit;
}
private static void crossOutMultiplesOf(int i) {
for (int multiple = 2 * i; multiple &lt; crossedOut.length; mu
ltiple += i) {
crossedOut[multiple] = true;
}
}
private static boolean notCrossed(int i) {
suggesting that we always throw away
our code when we are done?”
lun ca làm tôi bc mình. Tôi
lc đầu gn như thét lên: “Có phi
ông gi định chúng ta luôn luôn vt
b mã ngun sau khi làm xong?”
To my astonishment he nodded his
head and said: “Almost. I’m
suggesting that throwing away code is
a valid and useful operation. I’m
suggesting that you should not view it
as a loss. I’m suggesting that you not
get vested in your code.”
Tr li cho s kinh ngc ca tôi, g
ã
gt đầu nói: “Gn như như vy.
Tao gi định chuyn vt b ngun
mt vic đáng giá hu dng.
Tao gi định mày không nên xem đó
chuyn hoang phí. Tao gi định
mày không nên ôm khư khư cái
ngun ca mày.”
Th lành ngh #5: Bước nh
I didn’t like this; but I didn’t have an
argument to use against him. I just sat
there in silent disagreement.
Tôi chng khoái cái trò này nhưng
không mt chút lun c nào để
chng chi vi gã. Tôi ngi đó, lng
thinh trong s bt đồng.
“OK”
, he said, “Let's start over. The
way we work around here is to write
our unit tests first. “
This was patently absurd. I reacted
with intelligence: “Huh?”
“Let me show you,” he said. “Our task
is to create an array of prime factors
from a single integer.
What is the simplest test case you can
think of?”
“The first valid case is 2. And it should
return an array with just a single 2 in
it.”
“Right,” he said. And he wrote the
Được ri”, nói, “Mình làm li t
đầu. Cách ti tao làm
đây viết
kim th đơn v trước”.
Điu này hn . Tôi nhanh trí
phn ng ngay: “H?”
“Ð tao ch cho mày thy.” nói.
“Nhim v ca ti mình to ra mt
mng các tha s nguyên t t mt s
nguyên.
Mày nghĩ được trường hp kim th
nào đơn gin nht?”
“Trường hp hp đầu tiên 2.
kết qu cn tr v mt mng vi ch
mt s 2.”
“Ðúng ri.” nói. viết mt
His logic was annoying me. I shook
my head and nearly shouted: “Are you
while(!(success = try()));
www.codegym.vn / Page 30
return crossedOut[i] == false;
}
private static void putUncrossedIntegersIntoResult() {
result = new int[numberOfUncrossedIntegers()];
for (int j = 0, i = 2; i &lt; crossedOut.length; i++) {
if (notCrossed(i)) {
result[j++] = i;
}
}
}
private static int numberOfUncrossedIntegers() {
int count = 0;
for (int i = 2; i &lt; crossedOut.length; i++) {
if (notCrossed(i)) {
count++;
}
}
return count;
}
}
dẫn 8. TestGenerat
ePrimes.java (cui cùng)
import junit.framework.*;
public class TestGeneratePrimes extends TestCase {
public static void main(String args[]) {
junit.swingui.TestRunner.main(
new String[]{&quot;TestGeneratePrimes&quot;});
}
public TestGeneratePrimes(String name) {
super(name);
}
kim th đơn v như sau:
int factors[] = PrimeFactorizer.factor(2);
assertEquals(1, factors.length);
assertEquals(2, factors[0]);
}
Then he wrote the simplest code that
would allow the test case to compile.
Tiếp theo, viết mt đon rt
đơn gin để cho phép cái “test case”
trên biên dịch.
public class PrimeFactorizer {
public static int[] factor(int multiple) {
return new int[0];
}
}
He ran the test, and it failed saying:
“testT
wo(TestPrimeFactors): expected:
<1> but was: <0>”.
Now he looked at me and he said: “Do
the simplest thing possible to make
that test case pass.”
This was absurdity upon absurdity.
“What do you mean?” I said. “The
simplest thing would be to return an
array with a 2 in it.”
With a straight face, he said, “OK, do
that.”
“But that’s silly.” I said. “It’s the wrong
code. The real solution isn’t going to
just return a 2.”
chy kim th báo li:
“testTwo(TestPrimeF
actors): expected:
<1> but was: <0>”.
Ðến đây nhìn tôi nói: “Hãy làm
cách đơn gin nht để vượt qua
trường hp kim th đó.”
Bây gi thì chng cht sự . “Ý
ông sao?” Tôi hi. “Ðiu đơn giản
nhất hn tr v mt mng vi s 2
trong đó.”
tr li vi v mt nghiêm ngh: ,
làm vy đi.”
“Nhưng ng ngn quá.” Tôi nói, “Cái
này sai. Gii pháp thc s không
ch tr v có s 2.”
following unit test.
while(!(success = try()));
www.codegym.vn / Page 31
public void testPrimes() {
int[] nullArray = PrimeGenerator.generatePrimes(0);
assertEquals(nullArray.length, 0);
int[] minArray = PrimeGenerator.generatePrimes(2);
assertEquals(minArray.length, 1);
assertEquals(minArray[0], 2);
int[] threeArray = PrimeGenerator.generatePrimes(3);
assertEquals(threeArray.length, 2);
assertEquals(threeArray[0], 2);
assertEquals(threeArray[1], 3);
int[] centArray = PrimeGener
ator.generatePrimes(100);
assertEquals(centArray.length, 25);
assertEquals(centArray[24], 97);
}
public void testExhaustive() {
for (int i = 2; i &lt; 500; i++) {
verifyPrimeList(PrimeGenerator.generatePrimes(i));
}
}
private void verifyPrimeList(int[] list) {
for (int i = 0; i &lt; list.length; i++) {
verifyPrime(list[i]);
}
}
private void verifyPrime(int n) {
for (int factor = 2; factor &lt; n; factor++) {
asse
rt (n % factor != 0);
}
}
}
What a disaster! I thought that my
original solution had been top-notch.
Qu tai ho! Tôi c ng gii pháp
nguyên thy ca tôi thượng hạng.
“Yes, that’s true.” he said, “But just
humor me for a bit.”
I sighed, rolled my eyes, huffed and
puffed a bit, and then wrote:
a, đúng vy.” đáp li. “Nhưng
chiu lòng tao mt chút đi.”
Tôi th dài bc dc, đảo mt nhìn gã,
th dc mt chút ri bt đầu viết:
public static int[] factor(int multiple) {
return new int[]{2};
}
I ran the tests, and of course they
passed.
“What did that prove?” I asked.
“It proved that you could write a
function that finds
the prime factors of
two.” He said. “It also proves that the
test passes when the function
responds correctly to two.”
Tôi chy cái kim th tt nhiên
n c.
Tôi hi “Cái này chng minh được
điu gì vy?”
“Nó chng minh mày th viết mt
cái hàm tìm ra tha s nguyên t ca
2.” nói. “Nó cũng chng minh
kim th đã n khi cái hàm tr v
đúng vi s 2.”
I rolled my eyes again. This was
beneath my intelligence. I thought
being an apprentice here was
supposed to teach me s
omething.
“Now, what’s the simplest test case we
can add to this?” he asked me.
I couldn’t help myself. I dripped with
sarcasm as I said: “Gosh, Jerry,
maybe we should try a three.”
And though I expected it, I was also
incredulous. He actually wrote the
test case for three:
Tôi đảo mt ln na. My th này
nm dưới “trí tu ca tôi. Tôi ng
làm mt tay hc vic đây s được
dy mt cái gì đó cơ ch.
“Bây gi, trường hp kim th nào
đơn gin nht mình th đưa thêm
vào?
” Gã hi tôi.
Tôi không kìm được, tôi chì chiết mt
cách ma mai vi câu nói: “Ôi, Jerry
hay là mình nên th vi s 3?”
mc tôi hy vng, tôi không
tin rng gã viết kim th cho s 3 tht:
while(!(success = try()));
www.codegym.vn / Page 32
In some ways I still feel that way. I had
tried to show off my brilliance, but I
guess Mr. C values collaboration and
clarity more than individual brilliance.
Chút đó tôi vn còn cm thy như
vy. Tôi c phô trương tài năng ca
mình nhưng tôi đoán ông C đánh
giá cao sự cộng tác tính minh
bạch hơn tài năng nhân.
I had to admit that the program reads
much better than it did at the start. It
also works a bit better. I was pretty
pleased with the outcome. Also, in
spite of Jerry’s gruff attitude, it had
been fun working with him. I had
learned a lot.
Tôi phi thú nhn rng chương trình
này d xem hơn lúc khi đầu. li
làm vic tt hơn mt na. Tôi khá
hài lòng vi kết quả và, mc Jerry
thái độ cộc cằn, nhưng làm vic
vi tôi cũng thy vui. Tôi hc hi
được rt nhiu
Still, I was pretty discouraged with my
performance. I don’t think the folks
here are going to like me very much.
I’m not sure they’ll ever think I’m good
enough for them. This is going to be a
lot harder than I thought.
Du vy, tôi thy hơi chùn bước vi
chính hiu sut ca mình. Tôi không
dám nghĩ mấy tay đây s khoái
tôi cho lm. Tôi cũng không dám chc
đến bao bao gi h đánh giá tôi đủ
“ngon”. S th s khó khăn hơn tôi
nghĩ nhiu lm.
Thợ lành nghề #4 - Bài kiểm tra tính kiên nhẫn
12 July 2002
Dear Diary,
Last night I stared out the window for
hours watching the stars drifting
through the night sky. I felt conflicted
about the work I did with Jerry
yesterday. I learned a lot from working
with Jerry on the prime generator, but I
don’t think I impressed him very much.
And, frankly, I wasn’t all that
impressed with him. He spent a lot of
time polishing a piece of code that
worked just fine.
Ngày 12 tháng 7 năm 2002
Nht ký thân yêu,
Ti qua tôi ngi ta vào ca s hàng
gi, nhìn các sao trôi dạt trên bu
tri đêm. Tôi thy vic làm ca tôi
Jerry hôm qua nhiu xung đột. Tôi
hc hi rt nhiu trong khi làm vic vi
Jerry vi vn đề to s nguyên t,
nhưng tôi không tin tôi gây n tượng
vi gã. Và, thật tình nói, tôi
cũng không n cho lm. Tht ra,
tn khá nhiu thi gian mài dũa các
đon cho nhng đon này làm
vic ngon lành.
public void testThree() throws Exception {
int factors[] = PrimeFactorizer.factor(3);
assertEquals(1, factors.length);
assertEquals(3, factors[0]);
}
Running it produced the expected
failure: “testThree(TestPrimeFactors):
expected: <3> but was: <2>”.
“OK, Alphonse, do the simplest thing
that will make this test case pass.”
Impatiently, I took the keyboard and
typed the following:
Cái kim th này thông báo li như đã
đoán trước:
“test
Three(TestPrimeFactors):
expected: <3> but was: <2>”
Được ri Alphonse, làm cách đơn
gin nht để vượt qua cái kim th
này.”
St rut, tôi vi ly bàn phím
vào như sau:
public static int[] factor(int multiple) {
if (multiple == 2) {
return new int[]{2};
} else {
return new int[]{3};
}
}
I ran the tests, and they passed.
Jerry looked at me with an odd kind of
smile. He said: “OK, that passes the
tests. However, it’s not very bright, is
it?”
He’s t
he one who started this
nonsense and now he’s asking me if
this is bright? “I think this whole
Tôi chy my cái kim th chúng
đều n c.
Jerry nhìn tôi vi mt n cười bt
thường. nói: Được ri, my cái
kim th đó đạt ri. Tuy nhiên, nhìn
mã không sáng sa phi không?”
người bày cái trò ng ngn này
bây gi đi hi tôi sáng
sa không? “Tôi nghĩ rng toàn b bài
while(!(success = try()));
www.codegym.vn / Page 33
exercise is pretty dim.” I said.
tp này khá l m đó.” Tôi nói.
He ignored me and continued. “Every
time you add a new test case, you
have to make it pass by making the
code more general. Now go back and
make the simplest change that is more
general than your first solution.”
I thought about this for a minute. At
last Jerry had asked me something
that might require a few brain cells.
Yes, there was a more general
solution. I took the keyboard and
typed:
l đi tiếp tc.
C mi ln mày
thêm vào mt kim th mi, mày phi
làm cho đạt bng cách làm cho
ngun tng quát hơn. Bây gi th
đưa ra thay đổi đơn gin nht, tng
quát hơn gii pháp đầu tiên ca mày
xem sao.”
Tôi nghĩ v vn đề này chng mt
phút. Rt cuc Jerry đã hi tôi vài điu
cn đến tế bào não. Ðúng vy, gii
pháp tng quát hơn na. Tôi vi ly
bàn phím và gõ như sau:
public static int[] factor(int multiple) {
return new int[]{multiple};
}
The tests passed, and Jerry smiled.
But I st
ill couldn’t see how this was
getting us any closer to generating
prime factors. As far as I could tell, this
was a ridiculous waste of time.
Still, I wasn’t surprised when Jerry
asked me: “Now what’s the simplest
test case we can add?”
“Clearly that would be the case for
four.” I said impatiently. And I grabbed
Các kim th đều n c Jerry mm
cười nhưng tôi vn không th hình
dung làm sao my trò này đưa đến
chúng tôi đến gn hơn vi bài toán
to ra tha s nguyên t. Ðến mc
này đi
u duy nht tôi th phát biu
nhng cái trò quái đản này ch phí
thi gian.
Mc vy, tôi vn không ngc nhiên
my khi Jerry hi tôi: Bây gi, cái kim
th nào đơn gin nht mình th
đưa thêm vào?”
“Rõ ràng cho trường hp s 4.” Tôi
nói mt cách thiếu kiên nhn ri v ly
while(!(success = try()));
www.codegym.vn / Page 34
factors.add(new Integer(primes[i]));
}
}
return createFactorArray(factors);
}
private static int[] createFactorArray(List factors) {
int factorArray[] = new int[factors.size()];
int j = 0;
for (Iterator fi = factors.iterator(); fi.hasNext();) {
Integer factor = (Integer) fi.next();
factorArray[j++] = factor.intValue();
}
return factorArray;
}
}
I tested the program by running the
main program with several different
arguments. They all seemed to work.
Running it with 100 gave me 2, 2, 5,
and 5. Running it with 32767 gave me
7, 31, and 151. Running it with 32768
gave me fifteen twos.
Tôi kim tra chương trình bng cách
chy vi nhiu tham số khác nhau.
Mi th dường như n tho. Chy
chương trình vi giá tr tham s 100
cho tôi kết qu 2, 2, 5 5. Chy
vi 32767 cho tôi 7, 31 151. Chy
vi 32768 cho tôi 15 s 2.
Jerry just sat there and watched me.
He didn’t say a word. This made me
nervous, but I kept on massaging and
testing the code until I was happy with
it. Then I started writing the unit tests.
Jerry ngi nhìn tôi. chng nói na
li. Ðiu này làm tôi hơi hong nhưng
tôi tiếp tc nắn bóp th nghim
ngun cho đến lúc tôi hài lòng. Sau
đó, tôi bt đầu viết phn kim th đơn
v.
“What are you doing?” asked Jerry.
“The program works, so I’m writing the
unit tests.” I replied.
“Why do you need unit tests if the
program already works?” he said?
Jerry hi: “Mày làm gì vy?”
“Chương trình chy nên tôi đang viết
các kim th đơn v.” Tôi đáp li.
“Nếu chương trình đã chy thì vic
mày cn kim th đơn v?” hi
bàn phím và viết:
public void testFour() throws Exception {
int factors[] = PrimeFactorizer.factor(4);
assertEquals(2, factors.length);
assertEquals(2, factors[0]);
assertEquals(2, factors[1]);
}
“I expect the first assert will fail
because an array of size 1 will be
returned.” I said.
Sure enough, when I ran the test it
reported:
testFour(TestPrimeFactors):expected
<2> but
was <1>.
“I presume you’d like me to make the
simplest modification
that will make
all these tests pass, and will make the
factor method more general?” I asked.
Jerry just nodded.
I made a concerted effort to solve
only the test case at hand, ignoring
the test cases I knew would be next.
This galled me, but it was what Jerry
wanted. The result was:
Tôi nói “Tôi nghĩ cái ‘assert’ th nht
s hng s tr v 1 kích c ca
mng.”
Qu vy, khi chy kim th cho báo
cáo: “testFour(TestPrimeFactors)
:expected <2> but was <1>”.
Tôi hi: “Tôi
đoán ông mun tôi đưa
ra thay đổi đơn gin nht th để
các kim th đều đạt to ra
phương thc tha s tng quát hơn?”
Jerry gt đầu.
Tôi c gng tp trung gii quyết cho
cái kim th trước mt, l các kim
th tôi biết s đụng đến sau. Cái trò
này tht khó chu nhưng Jerry mun
vy. Kết qu như sau:
public class PrimeFactorizer {
public static int[] factor(int multiple) {
int currentFactor = 0;
the keyboard and wrote:
while(!(success = try()));
www.codegym.vn / Page 35
int factorRegister[] = new int[2];
for (; (multiple % 2) == 0; multiple /= 2) {
factorRegister[currentFactor++] = 2;
}
if (multiple != 1) {
factorRegister[currentFactor++] = multiple;
}
int factors[] = new int[currentFactor];
for (int i = 0; i &lt; currentFactor; i++) {
factors[i] = factorRegister[i];
}
return factors;
}
}
This passed all the tests, but was
pretty messy. Jerry scrunched up his
face as though he smelled something
rotten. He said: “We have to refactor
this before we go any further.”
“Wait.” I objected. “I agree that it’s a
bit messy. But shouldn’t we get it all
working first and then refactor it if
there’s time?”
Ðon này vượt qua tt c các
kim th, nhưng nhìn khá ln xn.
Jerry nhăn mt như th đánh hơi
được đó b thi. nói: “Mình phi
tái cu trúc cái này trước khi đi tiếp.”
Đợi đã.” Tôi phn đối. “Tôi đồng ý
ln xn nhưng sao mình không làm
cho chy trước ri tái cu tr
úc li
nếu có đủ thi gian?”
“Egad! No!” said Jerry. “We need to
refactor it now so that we can see the
true structure as it evolves. Otherwise
we’ll just keep piling mess upon mess,
and we’ll lose the sense of what we’re
doing.”
“OK.” I sighed. “Let's clean this up.”
“Tri! Không được!” Jerry nói. “Mình
cn phi tái cu trúc ngay lúc này để
th thy cu trúc thc s tiến hoá,
không thì ta ch chng cht cái ba
bn trên cái ba bn chúng ta s
không biết mình đang làm gì n
a.”
Được thôi.” Tôi th dài. “Thì dn
dp.”
while(!(success = try()));
www.codegym.vn / Page 36
The result follows:
Thế ri bn tôi tiến hành tái cu trúc
mt chút. Kết qu như sau:
public class PrimeFactorizer {
private static int factorIndex;
private static int[] factorRegister;
public static int[] factor(int multiple) {
initialize();
findPrimeFactors(multiple);
return copyToResult();
}
private static void initialize() {
factorIndex = 0;
factorRegister = new int[2];
}
private static void findPrimeFactors(int mul
tiple) {
for (; (multiple % 2) == 0; multiple /= 2) {
factorRegister[factorIndex++] = 2;
}
if (multiple != 1) {
factorRegister[factorIndex++] = multiple;
}
}
private static int[] copyToResult() {
int factors[] = new int[factorIndex];
So the two of us did a little refactoring.
while(!(success = try()));
www.codegym.vn / Page 37
for (int i = 0; i &lt; factorIndex; i++) {
factors[i] = factorRegister[i];
}
return factors;
}
}
“Time for the next test case.” Said
Jerry; and he passed me the
keyboard.
I still couldn’t see where this was
going, but there was no way out of it.
Obligingly, I typed in the following test
case:
Jerry tuyên b: “Ðến lúc cho cái kim
th tiếp theo.” chuyn bàn phím
cho tôi.
Tôi vn chưa th nhn ra trò này đi
đến đâu nhưng biết rng không
cách nào để thoát ra được. Mt cách
n
hân nhượng tôi viết cái kim th
như sau:
public void testFive() throws Exception {
int factors[] = PrimeFactorizer.factor(5);
assertEquals(1, factors.length);
assertEquals(5, factors[0]);
}
“That’s interesting.”, I said as I stared
at the green bar, “That one works
without change.”
“That is interesting.” Said Jerry. “Let's
try the next test case.”
Now I was intrigued. I hadn’t
expected the test case to just work. As
I thought about it, it was obvious
why it
worked, but I still hadn’t anticipated it.
I was pretty sure the next test case
would fail, so I typed it in and ran it.
“Tht thú.” Tôi nói trong khi nhìn
chm chp vào cái thanh màu xanh
(thanh trng thái kim th, màu xanh
tc đạt), “nó chy chng cn
thay đổi gì hết.”
“Ðúng thú”. Jerry ni tiếp. “Hãy
th vi kim th tiếp theo.”
Lúc này tôi ràng đã b thu hút. Tôi
không đoán được các trường hp
kim th làm vic như vy. Tôi khá
chc vic trường hp k
im th tiếp
theo s hng nên đã viết như sau
chy th:
while(!(success = try()));
www.codegym.vn / Page 38
public void testSix() throws Exception {
int factors[] = PrimeFactorizer.factor(6);
assertEquals(2, factors.length);
assertContains(factors, 2);
assertContains(factors, 3);
}
private void assertContains(int factors[], int n) {
String error = &quot;assertContains:&quot; + n;
for (int i = 0; i &lt; factors.length; i++) {
if (factors[i] == n) {
return;
}
}
fail(error);
}
“Yikes! That one passed too!” I cried.
“Inter
esting.” Nodded Jerry. “Seven is
going to work too, isn’t it?”
“Yeah, I think it is.”
“Then let's skip it and go for eight.
That one can’t pass!”
He was right. Eight had to fail because
the factorRegister array was too small.
“Úi! Cái kim th này cũng n luôn!”
tôi rú lên.
“Lý thú.” Jerry gt gù. “Vy 7 s chy
luôn phi không?”
“Vâng, tôi nghĩ vy.”
“Vy thì b đi đi thng ti 8,
s không qua được trường hp này
đâu!”
đúng. Vi trường hp ca 8 s
hng v
ì mng factorRegister quá nh.
public void testEight() throws Exception {
int factors[] = PrimeFactorizer.factor(8);
assertEquals(3, factors.length);
while(!(success = try()));
www.codegym.vn / Page 39
kim th đơn v như sau:
int factors[] = PrimeFactorizer.factor(2);
assertEquals(1, factors.length);
assertEquals(2, factors[0]);
}
Then he wrote the simplest code that
would allow the test case to compile.
Tiếp theo, viết mt đon rt
đơn gin để cho phép cái “test case”
trên biên dịch.
public class PrimeFactorizer {
public static int[] factor(int multiple) {
return new int[0];
}
}
He ran the test, and it failed saying:
“testTwo(TestPrimeFactors): expected:
<1> but was: <0>”.
Now he looked at me and he said: “Do
the simplest thing possible to make
that test case pass.”
This was absurdity upon absurdity.
“What do you mean?” I said. “The
simplest thing would be to return an
array with a 2 in it.”
With a straight face, he said, “OK, do
that.”
“But that’s silly.” I said. “It’s the wrong
code. The real solution isn’t going to
just return a 2.
chy kim th báo li:
“testTwo(TestPrimeFactors): expected:
<1> but was: <0>”.
Ðến đây nhìn tôi nói: “Hãy làm
cách đơn gin nht để vượt qua
trường hp kim th đó.”
Bây gi thì chng cht sự . “Ý
ông sao?” Tôi hi. “Ðiu đơn giản
nhất hn tr v mt mng vi s 2
trong đó.”
tr li vi v mt nghiêm ngh: ,
làm vy đi.”
“Nhưng ng ngn quá.” Tôi nói, “Cái
này sai. Gii pháp thc s không
ch tr v có s 2.”
assertContainsMany(factors, 3, 2);
}
private void assertContainsMany(int factors[], int n, int f) {
String error = &quot;assertContains(&quot; + n + &quot;,&quot; + f +
&quot;)&quot;;
int count = 0;
for (int i = 0; i &lt; factors.length; i++) {
if (factors[i] == f) {
count++;
}
}
if (count != n) {
fail(error);
}
}
“What a relief! It failed!”
“Yeah,” said Jerry, “for an array out of
bounds exception. You could get it to
pass by increasing the
size of
factorRegister, but that wouldn’t be
more general.”
“Let’s try it anyway, and then we’ll
solve the general problem of the array
size.”
So I changed the 2 to a 3 in the
initialize function, and got a green bar.
“OK,” I said, “what is the maximum
number of factors that a number can
have?”
“I think it’s something like log2 of the
number.” said Jerry.
“Ðúng là nh nhõm! nó hng ri!”
a.” Jerry đáp “Vì vượt quá ngoi l
kích thước ca mng. Mày th làm
vượt qua đư
c bng cách gia tăng
kích thước ca factorRegister nhưng
cách này không tng quát hơn được.
Thì c th xem sao ri mình gii quyết
vn đề chiu dài ca mng sau.”
Thế tôi đổi 2 thành 3 trong hàm
initialize và tôi có cái thanh màu xanh.
Được ri,” tôi nói. “ti đa các tha s
mà mt s có th có là bao nhiêu?”
“Tao nghĩ logarit cơ s 2 ca s đó
thì phi.” Jerry nói.
“Wait!” I said, “Maybe we’re chasing Đợi đã!” Tôi nói, “Có th mình đang
while(!(success = try()));
www.codegym.vn / Page 40
our tail. What is the largest number
we can handle? Isn’t it 2^64?”
“I’m pretty sure it can’t be larger than
that,” said Jerry.
“OK, then let's just make the size of
the factorRegister 100. That’s big
enough to handle any number we
throw at it.
“Fine by me.” said Jerry. “A hundred
integers is nothing to worry about.”
We tried it, and the tests still ran.
I looked at Jerry and said: “The next
test case is nine. That’s certainly going
to fail.”
“Let's try it.”
he said.
So I typed in the following:
đi lòng vòng đấy. S ln nht mình
th x my? không phi 2
mũ 64 sao?”
Jerry đáp “Tao chc không th ln
hơn con s đó.”
Được ri, vy thì th to ra chiu dài
ca factorRegister 100 đi. ln đủ
để x bt c s nào mình qung
cho nó.”
“Ðược thôi.” Jerry nói “100 s nguyên
thì chng có gì phi lo.”
Chúng tôi th điu này các kim
th vn chy.
Tôi nhìn Jerry nói: “kim th tiếp
theo ca tôi 9. Chc chn s
hng.”
G
ã đáp “Thì th đi.”
Vy là tôi viết mã như sau:
public void testNine() throws Exception {
int factors[] = PrimeFactorizer.factor(9);
assertEquals(2, factors.length);
assertContainsMany(factors, 2, 3);
}
“Good, that failed.” I said. “Making it
pass should be simple. I just need to
remove 2 as a special number in
findPrimeFactors, and use both 2 and
3 with some general algorithm.” So I
modified findPrimeFactors as follows:
“Tri, hng tht.” T
ôi nói. “Vượt
qua trường hp này cũng đơn gin
thôi. Tôi ch cn b đi 2 như mt s
đặc bit trong findPrimeFactors
dùng c 2 3 cho thut toán tng
quát.” Thế tôi đã điu chnh hàm
findPrimeFactors như sau:
while(!(success = try()));
www.codegym.vn / Page 41
private static void findPrimeFactors(int multiple) {
for (int factor = 2; multiple != 1; factor++) {
for (; (multiple % factor) == 0; multiple /= factor) {
factorRegister[factorIndex++] = factor;
}
}
}
“OK, that passes.” Said Jerry. “Now
what’s the next failing test case?”
“Well, the simple algorithm I used will
divide by non-primes as well as
primes. That won’t work right. That’s
why my first version of the program
was divided only by primes.
The first non-prime the algorithm will
divide by is four, so I imagine 4X4 will
fail.
Được ri, đã chy”. Jerry nói. “Bây
gi xem th cái kim th tiếp theo nào
s hng?”
m, thut toán đơn gin tôi dùng để
chia được t s phi ngu
yên t ln s
nguyên t. Kiu này s không thc
hin cho đúng được nên phiên bn
đầu ca chương trình ch chia được t
s nguyên t.
Thut toán đầu dành cho s phi
nguyên t s chia cho 4 nên tôi
mường tượng 4X4 s hng.
public void testSixteen() throws Exception {
int factors[] = PrimeFactorizer.factor(16);
assertEquals(4, factors.length);
assertContainsMany(factors, 4, 2);
}
“Ouch! That passes.” I said. “How
could that pass?”
“It passes, because all the
twos have
been removed before you try to divide
by four, so four is never found as a
factor. Remember, it also wasn’t found
as a factor of 8 or 4!”
“Ui! Cái kim th này chy ri.” Tôi
nói. “Làm sao nó qua được nh?”
“Nó qua được tt c các s 2 đã
được loi b trước khi mày th chia
cho 4, nên 4 không bao gi nhn ra
như mt tha s. Nên nh, cũng
không thy như mt tha s vi 8,
hoc là 4!”
while(!(success = try()));
www.codegym.vn / Page 42
“Of course!” I said. “All the primes are
removed before their composites.
The fact that the algorithm checks the
composites is irrelevant. But that
means I never needed the array of
prime numbers that I had in my first
version.”
“Tt nhiên!” tôi tr li. “Tt c các s
nguyên t b di b trước các đa hp.
Tht ra thut toán dùng để kim tra
các đa hp không liên quan hết,
nhưng điu đó nghĩa tôi không
h cn dãy ca các s nguyên t trong
phiên bn ban đầu ca mình.”
“Right.” sa
id Jerry. “That’s why I
deleted it.”
“Is this it then? Are we done?”
“Can you think of a failing test case?”
asked Jerry?
“I don’t know.” I said. “Let's try 1000.”
“Ah, the shotgun approach. OK, give
it a try.”
“Ðúng thế.” Jerry nói. “Ðó do tao
xoá nó.”
“Vy thì xong? Mình hoàn thành ri
phi không?”
Jerry hi: Mày th nghĩ ra được
cái test case nào b hng không?”
“Tôi không biết na, hãy th 1000 đi.”
Tôi tr li.
“À, tiếp cn kiu mnh bo. Được ri,
th đi.”
public void testThousand() throws Exception {
int factors[] = PrimeFactorizer.factor(1000);
assertEquals(6, factors.length);
assertContainsMany(factors, 3, 2);
assertContainsMany(factors, 3, 5);
}
“That worked! OK, how about...”
We tried several other test cases, but
they all passed. This version of the
program was much simpler than my
first version, and was faster too. No
“Nó chy luôn! Được ri, hay là…”
Chúng tôi viết nhiu
kim th khác
nhưng cái nào cũng n c. Phiên bn
này ca chương trình đơn gin hơn
phiên bn đầu tiên ca tôi nhiu
while(!(success = try()));
www.codegym.vn / Page 43
wonder Jerry deleted the first one. chy nhanh hơn na. Hèn chi Jerry đã
xoá đi phiên bn đầu.
What amazed me, and still amazes
me, is that we snuck up on the better
solution one test case at a time. I don’t
think I would ever have stumbled
upon this simple approach had we not
been inching forward one simple test
case at a time.
I wonder if that happens in bigger
projects? I learned something today.
Ðiu làm tôi kinh ngạc vn còn
làm tôi kinh ngc sau mi kim th
chún
g tôi li tiến gần hơn vi gii
pháp. Nếu không tiến lên vi mi
kim th thì tôi không nghĩ s th
đến theo cách đơn gin này.
Tôi không biết chuyn s xy ra vi
nhng d án ln hơn na? Hôm nay
tôi đã hc được đôi điu.
YӵQJ 3KLrQkP 1JKƭD
MRXUQH\PHQ ޖGݤܮޝQLPԥQ FӵXKӑFYLӋF
PDNHDPHVV PHܼNԥPHV WҥRPӝWKӛQÿӝQ
DSSUHQWLFH ԥޖSUHQWܼV KӑFQJKӅ
ZHOOUHFRJQL]HG ZHOޖUHNԥܳQDܼ]G ÿѭӧFF{QJQKұQ
VRIWZDUHGHYHORSPHQW ޖVܥIWZHԥUޖYHOԥSPԥQW SKiWWULӇQSKҫQPӅP
ILHUFH IܼԥV FăQJWKҷQJ
KLJKGHPDQG KDܼޖPܤޝQG 1KXFҫXFDR
RULHQWDWLRQ ޙܧޝULHQޖWݕԥQ VӵÿӏQKKѭӟQJ
OHYHORITXDOLW\ ޖOHYԥOԥYޖNZܥOԥWL PӭFÿӝFKҩWOѭӧQJ
RSSRUWXQLW\ ޙܥSԥޖWݕXޝQԥWL KӝL
SURJUDPPHU ޖSUԥݜܳUPԥU OұSWUuQKYLrQ
SULPHQXPEHU SUDܼPޖQݞPEԥU VӕQJX\rQWӕ
XQLWWHVW ޖMXޝQܼWWHVW NLӇPWUDÿѫQ
ZKLSWRJHWKHU SWԥޖܳHèԥU
LPSUHVVLYH ܼPޖSUHVܼY ҩQWѭӧQJ
FRPPHQWHG ޖNܥPHQW ÿmQKұQ[pW
QHDWO\ ޖQLޝWOL JӑQJjQJ
LQVWUXFWHG ܼQޖVWUݞNW KѭӟQJGүQ
VWDWLVWLFDO VޖWܼVWܼNԥO WKӕQJNr
FDVH NHܼV WUѭӡQJS
DVVXPHG ԥޖVMXޝP JLҧÿӏQK
VFHQDULR ޖQܤޝULԥݜ NӏFKEҧQ
JULQ ܳUܼQ FѭӡLWRHWRpW
VKRRNVEGVKHDG ݕݜN OҳFÿҫX
ILUH IDܼԥU VDWKҧL
SDWLHQW ޖSHܼݕԥQW NLrQQKүQ
VWDUWOHG ޖVWܤޝWԥOG JLұWPuQK
NHHSFRRO NLޝSNXޝO JLӳEuQKWƭQK
VLJKHG VDܼ WKӣGjL
ZDONWKURXJK ZܧޝNșUXޝ ÿLTXD
FOHDU NOܼԥU WK{QJWKRiQJ
while(!(success = try()));
www.codegym.vn / Page 44
7ӯYӵQJ 3KLrQkP 1JKƭD
MRXUQH\PHQ ޖGݤܮޝQLPԥQ FӵXKӑFYLӋF
PDNHDPHVV PHܼNԥPHV WҥRPӝWPӟKӛQÿӝQ
DSSUHQWLFH ԥޖSUHQWܼV KӑFQJKӅ
ZHOOUHFRJQL]HG ZHOޖUHNԥܳQDܼ]G ÿѭӧFF{QJQKұQ
VRIWZDUHGHYHORSPHQW ޖVܥIWZHԥUGܼޖYHOԥSPԥQW SKiWWULӇQSKҫQPӅP
ILHUFH IܼԥV FăQJWKҷQJ
KLJKGHPDQG KDܼGܼޖPܤޝQG 1KXFҫXFDR
RULHQWDWLRQ ޙܧޝULHQޖWHܼݕԥQ VӵÿӏQKKѭӟQJ
OHYHORITXDOLW\ ޖOHYԥOԥYޖNZܥOԥWL PӭFÿӝFKҩWOѭӧQJ
RSSRUWXQLW\ ޙܥSԥޖWݕXޝQԥWL FѫKӝL
SURJUDPPHU ޖSUԥݜܳUPԥU OұSWUuQKYLrQ
SULPHQXPEHU SUDܼPޖQݞPEԥU VӕQJX\rQWӕ
XQLWWHVW ޖMXޝQܼWWHVW NLӇPWUDÿѫQYӏ
ZKLSWRJHWKHU ZܼSWԥޖܳHèԥU
LPSUHVVLYH ܼPޖSUHVܼY ҩQWѭӧQJ
FRPPHQWHG ޖNܥPHQW ÿmQKұQ[pW
QHDWO\ ޖQLޝWOL JӑQJjQJ
LQVWUXFWHG ܼQޖVWUݞNW KѭӟQJGүQ
VWDWLVWLFDO VWԥޖWܼVWܼNԥO WKӕQJNr
FDVH NHܼV WUѭӡQJKӧS
DVVXPHG ԥޖVMXޝP JLҧÿӏQK
VFHQDULR VܼޖQܤޝULԥݜ NӏFKEҧQ
JULQ ܳUܼQ FѭӡLWRHWRpW
VKRRNVEGVKHDG ݕݜN OҳFÿҫX
ILUH IDܼԥU VDWKҧL
SDWLHQW ޖSHܼݕԥQW NLrQQKүQ
VWDUWOHG ޖVWܤޝWԥOG JLұWPuQK
NHHSFRRO NLޝSNXޝO JLӳEuQKWƭQK
VLJKHG VDܼ WKӣGjL
ZDONWKURXJK ZܧޝNșUXޝ ÿLTXD
FOHDU NOܼԥU WK{QJWKRiQJ
VHSDUDWH ޖVHSԥUԥW ULrQJ
LQLWLDOL]H ܼޖQܼݕԥO] NKӣLWҥR
H[HFXWH ޖHNNMXޝW WKLKjQK
ORDG OԥݜG L
LQWHJHUDUUD\ ޖܼQWܼԥUԥޖUHܼ PҧQJVӕQJX\rQ
FRQFHSW ޖNܥQVHSW éWѭӣQJ
EXULHG ޖEHUL FK{Q
KHDYHG KLޝY SKұSSKӗQJ
H[SRVH ܼNޖVSԥݜ] OӝUD
H[WUDFW ܼNޖVWUNW WUtFK[XҩW
XQQHFHVVDU\ ݞQޖQHVԥVHUL NK{QJFҫQWKLӃW
JHWULGRI ܳHWGԥY WKRiWNKӓL
LQEROG ܼQEԥݜOG LQÿұP
UHIDFWRU ULޖINWԥU FҩXWU~FOҥL
IRUFHG ޝVW EӏpS
YDULDEOH ޖYHԥULԥEԥO %LӃQ
VWDWLFILHOG ޖVWWܼNILޝOG WUѭӡQJWƭQK
FOHDUHU ޖNOܼԥUԥU U}UjQJQ
ORFDO ޖOԥݜNԥO ÿӏDSKѭѫQJ
LQIOXHQFH ޖܼQIOXԥQV ҧQKKѭӣQJ
PHVV\ ޖPHVL OӝQ[ӝQ
FOHDQVWKXS NOLޝQݞS GӑQGҽS
H[SUHVVLYH ܼNޖVSUHVܼY ELӇXFҧP
LQQDUGV ޖܼQԥG] EӝSKұQ
GHVFULSWLYH ޖVNUܼSWܼY P{Wҧ
UHDGDEOH ޖULޝGԥEԥO FyWKӇÿӑFÿѭӧF
GRXEOHQHJDWLYHV ޖGݞEԥOޖQHܳԥWܼY SKӫÿӏQKNpS
LQLWLDOL]DWLRQ LޙQL6+ԥOԥޖ]Ɨ6+ԥQ VӵNKӣLWҥR
LQGH[ ޖܼQGHNV PөFOөF
LQQHUORRS ܼQԥUOXޝS YzQJWURQJ
FRQIXVLQJ NԥQޖIMXޝƾ Jk\QKҫPOүQ
while(!(success = try()));
www.codegym.vn / Page 45
YӵQJ 3KLrQkP 1JKƭD
MRXUQH\PHQ ޖGݤܮޝQLPԥQ FӵXKӑFYLӋF
PDNHDPHVV PHܼNԥPHV WҥRPӝWKӛQÿӝQ
DSSUHQWLFH ԥޖSUHQWܼV KӑFQJKӅ
ZHOOUHFRJQL]HG ZHOޖUHNԥܳQDܼ]G ÿѭӧFF{QJQKұQ
VRIWZDUHGHYHORSPHQW ޖVܥIWZHԥUޖYHOԥSPԥQW SKiWWULӇQSKҫQPӅP
ILHUFH IܼԥV FăQJWKҷQJ
KLJKGHPDQG KDܼޖPܤޝQG 1KXFҫXFDR
RULHQWDWLRQ ޙܧޝULHQޖWݕԥQ VӵÿӏQKKѭӟQJ
OHYHORITXDOLW\ ޖOHYԥOԥYޖNZܥOԥWL PӭFÿӝFKҩWOѭӧQJ
RSSRUWXQLW\ ޙܥSԥޖWݕXޝQԥWL KӝL
SURJUDPPHU ޖSUԥݜܳUPԥU OұSWUuQKYLrQ
SULPHQXPEHU SUDܼPޖQݞPEԥU VӕQJX\rQWӕ
XQLWWHVW ޖMXޝQܼWWHVW NLӇPWUDÿѫQ
ZKLSWRJHWKHU SWԥޖܳHèԥU
LPSUHVVLYH ܼPޖSUHVܼY ҩQWѭӧQJ
FRPPHQWHG ޖNܥPHQW ÿmQKұQ[pW
QHDWO\ ޖQLޝWOL JӑQJjQJ
LQVWUXFWHG ܼQޖVWUݞNW KѭӟQJGүQ
VWDWLVWLFDO VޖWܼVWܼNԥO WKӕQJNr
FDVH NHܼV WUѭӡQJS
DVVXPHG ԥޖVMXޝP JLҧÿӏQK
VFHQDULR ޖQܤޝULԥݜ NӏFKEҧQ
JULQ ܳUܼQ FѭӡLWRHWRpW
VKRRNVEGVKHDG ݕݜN OҳFÿҫX
ILUH IDܼԥU VDWKҧL
SDWLHQW ޖSHܼݕԥQW NLrQQKүQ
VWDUWOHG ޖVWܤޝWԥOG JLұWPuQK
NHHSFRRO NLޝSNXޝO JLӳEuQKWƭQK
VLJKHG VDܼ WKӣGjL
ZDONWKURXJK ZܧޝNșUXޝ ÿLTXD
FOHDU NOܼԥU WK{QJWKRiQJ
VHSDUDWH ޖVHSԥUԥW ULrQJUӁ
LQLWLDOL]H ܼޖQܼݕԥODܼ] NKӣLWҥR
H[HFXWH ޖHNVܼNMXޝW WKLKjQK
ORDG OԥݜG WҧL
LQWHJHUDUUD\ ޖܼQWܼGݤԥUԥޖUHܼ PҧQJVӕQJX\rQ
FRQFHSW ޖNܥQVHSW éWѭӣQJ
EXULHG ޖEHUL FK{Q
KHDYHG KLޝY SKұSSKӗQJ
H[SRVH ܼNޖVSԥݜ] OӝUD
H[WUDFW ܼNޖVWUNW WUtFK[XҩW
XQQHFHVVDU\ ݞQޖQHVԥVHUL NK{QJFҫQWKLӃW
JHWULGRI ܳHWUܼGԥY WKRiWNKӓL
LQEROG ܼQEԥݜOG LQÿұP
UHIDFWRU ULޖINWԥU FҩXWU~FOҥL
IRUFHG IܧޝVW EӏpS
YDULDEOH ޖYHԥULԥEԥO %LӃQ
VWDWLFILHOG ޖVWWܼNILޝOG WUѭӡQJWƭQK
FOHDUHU ޖNOܼԥUԥU U}UjQJKѫQ
ORFDO ޖOԥݜNԥO ÿӏDSKѭѫQJ
LQIOXHQFH ޖܼQIOXԥQV ҧQKKѭӣQJ
PHVV\ ޖPHVL OӝQ[ӝQ
FOHDQVWKXS NOLޝQݞS GӑQGҽS
H[SUHVVLYH ܼNޖVSUHVܼY ELӇXFҧP
LQQDUGV ޖܼQԥG] EӝSKұQ
GHVFULSWLYH GܼޖVNUܼSWܼY P{Wҧ
UHDGDEOH ޖULޝGԥEԥO FyWKӇÿӑFÿѭӧF
GRXEOHQHJDWLYHV ޖGݞEԥOޖQHܳԥWܼY SKӫÿӏQKNpS
LQLWLDOL]DWLRQ LޙQL6+ԥOԥޖ]Ɨ6+ԥQ VӵNKӣLWҥR
LQGH[ ޖܼQGHNV PөFOөF
LQQHUORRS ܼQԥUOXޝS YzQJWURQJ
FRQIXVLQJ NԥQޖIMXޝ]ܼƾ Jk\QKҫPOүQ
while(!(success = try()));
www.codegym.vn / Page 46
LWHUDWHXS ޖܼWԥUHܼWݞS OһSOҥL
HPXODWH ޖHPMԥOHܼW WKLÿXD
H[SODQDWRU\ ܼNޖVSOQԥWԥUL JLҧLWKtFK
GHDOWZLWK GLޝOZܼè [ӱOê
JHWWKHKDQJRI ܳHWèLޝKƾԥY KLӇXYLӋF
PLVFHOODQHRXV ޙPܼVԥOޖHܼQLԥV EDRKjP
EDUHO\ ޖEHԥOL YӯDÿӫ
JHRPHWULF ޙGݤLޝԥޖPHWUܼN KuQKKӑF
IUDJPHQW ޖIUܳPԥQW PLӃQJ
KDQJVWRJHWKHU KƾWԥޖܳHèԥU JҳQEyYӟLQKDX
VFRZO VNDݜO FDXFy
PHHNO\ ޖPLޝNOL KLӅQOjQK
UHDGWKURXJK ޖULޝGޙșUXޝ ĈӑFTXD
LPSURYHPHQW ܼPޖSUXޝYPԥQW VӵFҧLWLӃQ
UHOHYDQW ޖUHOԥYԥQW OLrQTXDQWKtFKKӧS
PXOWLSOH ޖPݞOWܼSԥO QKLӅX
JUDE ܳUE YӗOҩ\
DSSURYDO ԥޖSUXޝYԥO SKrGX\ӋW
WDNHQDEDFN WHܼNԥޖEN VӱQJVӕW
VTXDUHURRW ޙVNZHԥޖUXޝW FăQEұFKDL
FDOFXODWH ޖNONMԥOHܼW WtQKWRiQ
VKHHSLVKO\ ޖݕLޝSܼݕOL QJѭӧQJQJQJ
UHZULWH ޙULޝޖUDܼW YLӃWOҥL
UDWLRQDOH ޙUݕԥޖQܤޝO VӣOêOXұQ
DSSURSULDWHO\ ԥޖSUԥݜSULԥWOL WKtFKKӧS
EDUN EܤޝN WUXWUpR
JXOS ܳݞOS QXӕWQѭӟFEӑW
IUDFWLRQDO ޖIUNݕԥQԥO SKkQVӕ
LWHUDWLRQOLPLW ޙܼWԥUޖHܼݕԥQޖOܼPܼW JLӟLKҥQOһSOҥL
OLWWHU ޖOܼWԥU [ҧUiF
LQFUHPHQW ޖܼƾNUԥPԥQW WăQJ
SDUDQRLG ޖSUԥQܧܼG KRDQJWѭӣQJ
VLOO\ ޖVܼOL QJӕF
QHUYRXV ޖQܮޝYԥV OROҳQJ
QDJJLQJ ޖQܳܼƾ FҵQQKҵQ
FRYHUHG ޖNݞYԥU ÿӅFұS
JUXPEOHG ޖܳUݞPEԥO FjXQKjX
LPSDWLHQW ܼPޖSHܼݕԥQW QyQJQҧ\
DOOD\ ԥޖOHܼ [RDGӏX
UHOHQWHG ޖOHQW PӫLOzQJ
VFUROO VNUԥݜO FXӝQ[XӕQJ
GHDGLQWKHH\H GHGܼQèLޝ OҥQKOQJ
PRGXOH ޖPܥGݤO P{ÿXQ
ODVWORQJ OܤޝVWOܥƾ WӗQWҥLOkX
VWULGHRII VWUDܼGܥI VҧLEѭӟF
WRSQRWFK ޙWܥSޖQܥWݕ ÿӍQKFDR
EULOOLDQFH ޖEUܼOMԥQV ViQJFKyL
FROODERUDWLRQ NԥޙOEԥޖUHܼݕԥQ VӵSWiF
FODULW\ ޖNOUԥWL WURQJWUҿR
LQGLYLGXDO ޙܼQޖYܼXԥO FiQKkQ
RXWFRPH ޖDݜWNݞP NӃWFөF
JUXII ܳUݞI FӝFFҵQ
DWWLWXGH ޖWܼWݕXޝG 7KiLÿӝ
GLVFRXUDJHG ޖVNݞUܼG QҧQOzQJ
IRONV IRݜNV KӝL
GULIWLQJ GUܼIW WU{LGҥW
FRQIOLFWHG NԥQޖINWܼG PkXWKXүQ
IUDQNO\ ޖIUƾNOL WKҷQJWKҳQ
SROLVK ޖSܥOܼݕ ÿiQKEyQJ
DUJXPHQW ޖܤޝܳMԥPԥQW WKDP
YHQWXUHG ޖYHQWݕԥU PҥRKLӇP
GLVEHOLHI ޙGܼVޖOLޝI VӵKRjLQJKL
while(!(success = try()));
www.codegym.vn / Page 47
LWHUDWHXS ޖܼWԥUHܼWݞS OһSOҥL
HPXODWH ޖHPMԥOHܼW WKLÿXD
H[SODQDWRU\ ܼNޖVSOQԥWԥUL JLҧLWKtFK
GHDOWZLWK GLޝOè [ӱ
JHWWKHKDQJRI ܳHWèLޝKƾԥY KLӇXYLӋF
PLVFHOODQHRXV ޙPܼVԥOޖHܼQLԥV EDRKjP
EDUHO\ ޖEHԥOL YӯDÿӫ
JHRPHWULF ޙGݤԥޖPHWN KuQKKӑF
IUDJPHQW ޖIUܳPԥQW PLӃQJ
KDQJVWRJHWKHU KƾWԥޖܳHèԥU JҳQEyLQKDX
VFRZO VNDݜO FDXFy
PHHNO\ ޖPLޝNOL KLӅQOjQK
UHDGWKURXJK ޖULޝGޙșUXޝ ĈӑFTXD
LPSURYHPHQW ܼPޖSUXޝYPԥQW VӵFҧLWLӃQ
UHOHYDQW ޖUHOԥYԥQW OLrQTXDQWKtFKS
PXOWLSOH ޖPݞOWܼSԥO QKLӅX
JUDE ܳUE YӗOҩ\
DSSURYDO ԥޖSUXޝYԥO SKrGX\ӋW
WDNHQDEDFN WNԥޖEN VӱQJVӕW
VTXDUHURRW ޙVNZHԥޖUXޝW FăQEұFKDL
FDOFXODWH ޖNONMԥOHܼW WtQKWRiQ
VKHHSLVKO\ ޖݕLޝݕOL QJѭӧQJQJQJ
UHZULWH ޙULޝޖUDܼW YLӃWOҥL
UDWLRQDOH ޙUݕԥޖQܤޝO OêOXұQ
DSSURSULDWHO\ ԥޖSUԥݜSULԥWOL WKtFKKӧS
EDUN EܤޝN WUXWUpR
JXOS ܳݞOS QXӕWQѭӟFEӑW
IUDFWLRQDO ޖIUNݕԥQԥO SKkQ
LWHUDWLRQOLPLW ޙܼWԥUޖHܼݕԥQޖOܼPܼW JLӟLKҥQOһSOҥL
OLWWHU ޖOܼWԥU [ҧUiF
LQFUHPHQW ޖܼƾNUԥPԥQW WăQJ
SDUDQRLG ޖSUԥQܧܼG KRDQJWѭӣQJ
VLOO\ ޖVܼOL QJӕF
QHUYRXV ޖQܮޝYԥV OROҳQJ
QDJJLQJ ޖQܳܼƾ FҵQQKҵQ
FRYHUHG ޖNݞYԥU ÿӅFұS
JUXPEOHG ޖܳUݞPEԥO FjXQKjX
LPSDWLHQW ܼPޖSHܼݕԥQW QyQJQҧ\
DOOD\ ԥޖOHܼ [RDGӏX
UHOHQWHG UܼޖOHQW PӫLOzQJ
VFUROO VNUԥݜO FXӝQ[XӕQJ
GHDGLQWKHH\H GHGܼQèLޝDܼ OҥQKOQJ
PRGXOH ޖPܥGݤXޝO P{ÿXQ
ODVWORQJ OܤޝVWOܥƾ WӗQWҥLOkX
VWULGHRII VWUDܼGܥI VҧLEѭӟF
WRSQRWFK ޙWܥSޖQܥWݕ ÿӍQKFDR
EULOOLDQFH ޖEUܼOMԥQV ViQJFKyL
FROODERUDWLRQ NԥޙOEԥޖUHܼݕԥQ VӵKӧSWiF
FODULW\ ޖNOUԥWL WURQJWUҿR
LQGLYLGXDO ޙܼQGܼޖYܼGݤXԥO FiQKkQ
RXWFRPH ޖDݜWNݞP NӃWFөF
JUXII ܳUݞI FӝFFҵQ
DWWLWXGH ޖWܼWݕXޝG 7KiLÿӝ
GLVFRXUDJHG GܼޖVNݞUܼGݤG QҧQOzQJ
IRONV IRݜNV KӝL
GULIWLQJ GUܼIW WU{LGҥW
FRQIOLFWHG NԥQޖIOܼNWܼG PkXWKXүQ
IUDQNO\ ޖIUƾNOL WKҷQJWKҳQ
SROLVK ޖSܥOܼݕ ÿiQKEyQJ
DUJXPHQW ޖܤޝܳMԥPԥQW WKDPVӕ
YHQWXUHG ޖYHQWݕԥU PҥRKLӇP
GLVEHOLHI ޙGܼVEܼޖOLޝI VӵKRjLQJKL
WHVW\ ޖWHVWL FӭQJUҳQ
DVVHUW ԥޖVܮޝW NKҷQJÿӏQK
GXPEIRXQGHG ޙGݞPޖIDݜQG FKӃWOһQJ
IXULRXV ޖIMݜԥULԥV JLұQ
UHDFKRYHU ULޝWݕޖԥݜYԥU YѭѫQWӟL
SUHVWLJH SUHVޖWݤ X\WtQ
EUXWH EUXޝW YNJSKX
DSSUHQWLFHVKLS ԥޖSUHQWܼVݕܼS VӵKӑFYLӋF
FRPSOLPHQWDU\ ޙNܥPSOܼޖPHQWԥUL FDQJӧL
WKRXJKW șܧޝW êQJKƭ
UDFH UHܼV FXӝFÿXD
JODUH ܳOHԥU FKyLPҳW
FDOPO\ ޖNܤޝPOL ÿLӅPWƭQK
VSXWWHUHG ޖVSݞWԥU OҳSEҳS
LQWHOOLJHQW ܼQޖWHOܼԥQW WK{QJPLQK
YHVWHG ޖYHVWܼG EiPUӏW
WKURZDZD\ șUԥݜԥޖZHܼ YӭWÿL
EDWFKRI EWݕԥY O{
EOXUWHG EOܮUW EXӝWPLӋQJ
YDOXH ޖYOMXޝ JLiW
DFFLGHQWDOO\ ޙNޖGHQWԥOL WuQKFӡ
HIIRUW ޖHIԥW FӕJҳQJ
GLVN VN ÿƭD
ZLQFHG QV QKăQPһW
QRG QܥG JұWÿҫX
NQRZLQJO\ ޖQԥݜܼƾOL Fӕê
UHFUHDWH ޙULޝNULޖHܼW WiLWҥR
UHIXWH ޖIMXޝW EiF
IHOW IHOW FҧPWKҩ\
ZKHWKHU ޖZHèԥU OLӋX
UHJUHW ޖܳUHW KӕLWLӃF
while(!(success = try()));
www.codegym.vn / Page 48
SDUDQRLG ޖSUԥQܧܼG KRDQJWѭӣQJ
VLOO\ ޖVܼOL QJӕF
QHUYRXV ޖQܮޝYԥV OROҳQJ
QDJJLQJ ޖQܳܼƾ FҵQQKҵQ
FRYHUHG ޖNݞYԥU ÿӅFұS
JUXPEOHG ޖܳUݞPEԥO FjXQKjX
LPSDWLHQW ܼPޖSHܼݕԥQW QyQJQҧ\
DOOD\ ԥޖOHܼ [RDGӏX
UHOHQWHG ޖOHQW PӫLOzQJ
VFUROO VNUԥݜO FXӝQ[XӕQJ
GHDGLQWKHH\H GHGܼQèLޝ OҥQKOQJ
PRGXOH ޖPܥGݤO P{ÿXQ
ODVWORQJ OܤޝVWOܥƾ WӗQWҥLOkX
VWULGHRII VWUDܼGܥI VҧLEѭӟF
WRSQRWFK ޙWܥSޖQܥWݕ ÿӍQKFDR
EULOOLDQFH ޖEUܼOMԥQV ViQJFKyL
FROODERUDWLRQ NԥޙOEԥޖUHܼݕԥQ VӵSWiF
FODULW\ ޖNOUԥWL WURQJWUҿR
LQGLYLGXDO ޙܼQޖYܼXԥO FiQKkQ
RXWFRPH ޖDݜWNݞP NӃWFөF
JUXII ܳUݞI FӝFFҵQ
DWWLWXGH ޖWܼWݕXޝG 7KiLÿӝ
GLVFRXUDJHG ޖVNݞUܼG QҧQOzQJ
IRONV IRݜNV KӝL
GULIWLQJ GUܼIW WU{LGҥW
FRQIOLFWHG NԥQޖINWܼG PkXWKXүQ
IUDQNO\ ޖIUƾNOL WKҷQJWKҳQ
SROLVK ޖSܥOܼݕ ÿiQKEyQJ
DUJXPHQW ޖܤޝܳMԥPԥQW WKDP
YHQWXUHG ޖYHQWݕԥU PҥRKLӇP
GLVEHOLHI ޙGܼVޖOLޝI VӵKRjLQJKL
WHVW\ ޖWHVWL FӭQJUҳQ
DVVHUW ԥޖVܮޝW NKҷQJÿӏQK
GXPEIRXQGHG ޙGݞPޖIDݜQGܼG FKӃWOһQJ
IXULRXV ޖIMݜԥULԥV JLұQGӳ
UHDFKRYHU ULޝWݕޖԥݜYԥU YѭѫQWӟL
SUHVWLJH SUHVޖWLޝݤ X\WtQ
EUXWH EUXޝW YNJSKX
DSSUHQWLFHVKLS ԥޖSUHQWܼVݕܼS VӵKӑFYLӋF
FRPSOLPHQWDU\ ޙNܥPSOܼޖPHQWԥUL FDQJӧL
WKRXJKW șܧޝW êQJKƭ
UDFH UHܼV FXӝFÿXD
JODUH ܳOHԥU FKyLPҳW
FDOPO\ ޖNܤޝPOL ÿLӅPWƭQK
VSXWWHUHG ޖVSݞWԥU OҳSEҳS
LQWHOOLJHQW ܼQޖWHOܼGݤԥQW WK{QJPLQK
YHVWHG ޖYHVWܼG EiPUӏW
WKURZDZD\ șUԥݜԥޖZHܼ YӭWÿL
EDWFKRI EWݕԥY O{
EOXUWHG EOܮUW EXӝWPLӋQJ
YDOXH ޖYOMXޝ JLiWUӏ
DFFLGHQWDOO\ ޙNVܼޖGHQWԥOL WuQKFӡ
HIIRUW ޖHIԥW FӕJҳQJ
GLVN GܼVN ÿƭD
ZLQFHG ZܼQV QKăQPһW
QRG QܥG JұWÿҫX
NQRZLQJO\ ޖQԥݜܼƾOL Fӕê
UHFUHDWH ޙULޝNULޖHܼW WiLWҥR
UHIXWH UܼޖIMXޝW EiFEӓ
IHOW IHOW FҧPWKҩ\
ZKHWKHU ޖZHèԥU OLӋX
UHJUHW UܼޖܳUHW KӕLWLӃF
LQVWDQW ޖܼQVWԥQW OұSWӭF
VWUXFWXUH ޖVWUݞNWݕԥU NӃWFҩX
ZRXQGXS ޙZDݜQGޖݞS TXҩQOҥL
DVWRQLVKPHQW ԥޖVWܥQܼݕPԥQW VӵNLQKQJҥF
YDOLG ޖYOܼG FyJLiW
XVHIXO ޖMXޝVIԥO FytFK
YLHZ YMXޝ 4XDQJFҧQK
VXJJHVW VԥޖGݤHVW JӧLê
DJDLQVW ԥޖܳHQVW FKӕQJOҥL
VLOHQW ޖVDܼOԥQW LPOһQJ
GLVDJUHHPHQW ޙGܼVԥޖܳULޝPԥQW EҩWÿӗQJêNLӃQ
SDWHQWO\ ޖSHܼWԥQWOL QKҽQKjQJ
DEVXUG ԥEޖVܮޝG QJӟQJҭQ
UHDFWHG ULޖNW SKҧQӭQJ
UHWXUQ UܼޖޝQ WUҧ
FRPSLOH NԥPޖSDܼO ELrQGӏFK
DEVXUGLW\ ԥEޖ]ܮޝWL VӵY{
VLPSOH ޖVܼPSԥO JLҧQ
KXPRU ޖKMXޝPԥU FKLӅXOzQJ
KXIIDQGSXII KݞIQGSݞI WKәQKӇQ
SURYH SUXޝY FKӭQJWӓ
UHVSRQG ޖVSܥQG WUҧOӡL
EHQHDWK ޖQLޝș ӣWUrQ
GULS GUܼS FKӍFKLӃW
VDUFDVP ޖVܤޝN]ԥP PӍDPDL
LQFUHGXORXV ܼQޖNUHGݤԥOԥV NK{QJWLQ
IDLOXUH ޖIOMԥU WKҩWEҥL
,PSDWLHQWO\ ܼPޖSHܼݕԥQWOL 6ӕWUXӝW
RGG ܥG EҩWWKѭӡQJ
EULJKW EUDܼW ViQJFKyL
QRQVHQVH ޖQܥQVԥQV Y{
while(!(success = try()));
www.codegym.vn / Page 49
WHVW\ ޖWHVWL FӭQJUҳQ
DVVHUW ԥޖVܮޝW NKҷQJÿӏQK
GXPEIRXQGHG ޙGݞPޖIDݜQG FKӃWOһQJ
IXULRXV ޖIMݜԥULԥV JLұQ
UHDFKRYHU ULޝWݕޖԥݜYԥU YѭѫQWӟL
SUHVWLJH SUHVޖWݤ X\WtQ
EUXWH EUXޝW YNJSKX
DSSUHQWLFHVKLS ԥޖSUHQWܼVݕܼS VӵKӑFYLӋF
FRPSOLPHQWDU\ ޙNܥPSOܼޖPHQWԥUL FDQJӧL
WKRXJKW șܧޝW êQJKƭ
UDFH UHܼV FXӝFÿXD
JODUH ܳOHԥU FKyLPҳW
FDOPO\ ޖNܤޝPOL ÿLӅPWƭQK
VSXWWHUHG ޖVSݞWԥU OҳSEҳS
LQWHOOLJHQW ܼQޖWHOܼԥQW WK{QJPLQK
YHVWHG ޖYHVWܼG EiPUӏW
WKURZDZD\ șUԥݜԥޖZHܼ YӭWÿL
EDWFKRI EWݕԥY O{
EOXUWHG EOܮUW EXӝWPLӋQJ
YDOXH ޖYOMXޝ JLiW
DFFLGHQWDOO\ ޙNޖGHQWԥOL WuQKFӡ
HIIRUW ޖHIԥW FӕJҳQJ
GLVN VN ÿƭD
ZLQFHG QV QKăQPһW
QRG QܥG JұWÿҫX
NQRZLQJO\ ޖQԥݜܼƾOL Fӕê
UHFUHDWH ޙULޝNULޖHܼW WiLWҥR
UHIXWH ޖIMXޝW EiF
IHOW IHOW FҧPWKҩ\
ZKHWKHU ޖZHèԥU OLӋX
UHJUHW ޖܳUHW KӕLWLӃF
LQVWDQW ޖܼQVWԥQW OұSWӭF
VWUXFWXUH ޖVWUݞNWݕԥU NӃWFҩX
ZRXQGXS ޙZDݜQGޖݞS TXҩQOҥL
DVWRQLVKPHQW ԥޖVWܥQܼݕPԥQW VӵNLQKQJҥF
YDOLG ޖYOܼG FyJLiWUӏ
XVHIXO ޖMXޝVIԥO FytFK
YLHZ YMXޝ 4XDQJFҧQK
VXJJHVW VԥޖGݤHVW JӧLê
DJDLQVW ԥޖܳHQVW FKӕQJOҥL
VLOHQW ޖVDܼOԥQW LPOһQJ
GLVDJUHHPHQW ޙGܼVԥޖܳULޝPԥQW EҩWÿӗQJêNLӃQ
SDWHQWO\ ޖSHܼWԥQWOL QKҽQKjQJ
DEVXUG ԥEޖVܮޝG QJӟQJҭQ
UHDFWHG ULޖNW SKҧQӭQJ
UHWXUQ UܼޖWܮޝQ WUҧYӅ
FRPSLOH NԥPޖSDܼO ELrQGӏFK
DEVXUGLW\ ԥEޖ]ܮޝGܼWL VӵY{Oê
VLPSOH ޖVܼPSԥO JLҧQGӏ
KXPRU ޖKMXޝPԥU FKLӅXOzQJ
KXIIDQGSXII KݞIQGSݞI WKӣKәQKӇQ
SURYH SUXޝY FKӭQJWӓ
UHVSRQG UܼޖVSܥQG WUҧOӡL
EHQHDWK EܼޖQLޝș ӣWUrQ
GULS GUܼS FKӍFKLӃW
VDUFDVP ޖVܤޝN]ԥP PӍDPDL
LQFUHGXORXV ܼQޖNUHGݤԥOԥV NK{QJWLQ
IDLOXUH ޖIHܼOMԥU WKҩWEҥL
,PSDWLHQWO\ ܼPޖSHܼݕԥQWOL 6ӕWUXӝW
RGG ܥG EҩWWKѭӡQJ
EULJKW EUDܼW ViQJFKyL
QRQVHQVH ޖQܥQVԥQV Y{Oê
GLP GܼP OӡPӡ
LJQRUH ܼܳޖQܧޝU /jP
JHQHUDO ޖGݤHQԥUԥO FKXQJ
EUDLQFHOOV EUHܼQVHO WӃEjRQmR
FORVHU NOԥݜ]HU JҫQQ
ULGLFXORXV ޖGܼNMԥOԥV OӕEӏFK
SUHVXPH SUܼޖ]MXޝP SKӓQJÿRiQ
PRGLILFDWLRQ ޙPܥGܼIܼޖNHܼݕԥQ VӵVӱDÿәL
FRQFHUWHG NԥQޖVܮޝWܼG SKӕLS
DWKDQG WKQG WURQJWҫPWD\
JDOOHG ܳܧޝO NKyFKӏX
PHVV\ ޖPHVL OӝQ[ӝQ
VFUXQFKXS VNUݞQWݕݞS WKXGӑQ
URWWHQ ޖUܥWԥQ WKӕLUӳD
REMHFWHG ޖܥEܼNW SKҧQÿӕL
HYROYH ܼޖYܥOY WLӃQKyD
REOLJLQJO\ ԥޖEODܼܼƾOL PDQJѫQ
VWDUHG VWHԥU QKuQFKҵPFKҵP
LQWULJXHG ܼQޖWULޝܳ EӏWKXK~W
DQWLFLSDWHG QޖWܼVܼSHܼW GӵÿRiQWUѭӟF
UHOLHI ޖOLޝI VӵFӭXWӃ
H[FHSWLRQ ܼNޖVHSݕԥQ QJRҥL
LQFUHDVH ܼQޖNULޝV WăQJ
FKDVLQJWDLO HܼVWHܼO ÿLOzQJYzQJ
KDQGOH ޖKQGԥO [ӱ
DOJRULWKP ޖOܳԥèԥP WKXұWWRiQ
PRGLILHG ޖPܥGܼIG VӱDÿәL
GLYLGH ޖYDܼG FKLD
FRPSRVLWH ޖNܥPSԥW ÿDS
LUUHOHYDQW ܼޖUHOԥYԥQW NK{QJOLrQTXDQ
DSSURDFK ԥޖSUԥݜWݕ FiFKWLӃSFұQ
while(!(success = try()));
www.codegym.vn / Page 50
LQVWDQW ޖܼQVWԥQW OұSWӭF
VWUXFWXUH ޖVWUݞNWݕԥU NӃWFҩX
ZRXQGXS ޙZDݜQGޖݞS TXҩQOҥL
DVWRQLVKPHQW ԥޖVWܥQܼݕPԥQW VӵNLQKQJҥF
YDOLG ޖYOܼG FyJLiW
XVHIXO ޖMXޝVIԥO FytFK
YLHZ YMXޝ 4XDQJFҧQK
VXJJHVW VԥޖGݤHVW JӧLê
DJDLQVW ԥޖܳHQVW FKӕQJOҥL
VLOHQW ޖVDܼOԥQW LPOһQJ
GLVDJUHHPHQW ޙGܼVԥޖܳULޝPԥQW EҩWÿӗQJêNLӃQ
SDWHQWO\ ޖSHܼWԥQWOL QKҽQKjQJ
DEVXUG ԥEޖVܮޝG QJӟQJҭQ
UHDFWHG ULޖNW SKҧQӭQJ
UHWXUQ UܼޖޝQ WUҧ
FRPSLOH NԥPޖSDܼO ELrQGӏFK
DEVXUGLW\ ԥEޖ]ܮޝWL VӵY{
VLPSOH ޖVܼPSԥO JLҧQ
KXPRU ޖKMXޝPԥU FKLӅXOzQJ
KXIIDQGSXII KݞIQGSݞI WKәQKӇQ
SURYH SUXޝY FKӭQJWӓ
UHVSRQG ޖVSܥQG WUҧOӡL
EHQHDWK ޖQLޝș ӣWUrQ
GULS GUܼS FKӍFKLӃW
VDUFDVP ޖVܤޝN]ԥP PӍDPDL
LQFUHGXORXV ܼQޖNUHGݤԥOԥV NK{QJWLQ
IDLOXUH ޖIOMԥU WKҩWEҥL
,PSDWLHQWO\ ܼPޖSHܼݕԥQWOL 6ӕWUXӝW
RGG ܥG EҩWWKѭӡQJ
EULJKW EUDܼW ViQJFKyL
QRQVHQVH ޖQܥQVԥQV Y{
GLP GܼP OӡPӡ
LJQRUH ܼܳޖQܧޝU /jPOѫ
JHQHUDO ޖGݤHQԥUԥO FKXQJ
EUDLQFHOOV EUHܼQVHO WӃEjRQmR
FORVHU NOԥݜ]HU JҫQKѫQ
ULGLFXORXV UܼޖGܼNMԥOԥV OӕEӏFK
SUHVXPH SUܼޖ]MXޝP SKӓQJÿRiQ
PRGLILFDWLRQ ޙPܥGܼIܼޖNHܼݕԥQ VӵVӱDÿәL
FRQFHUWHG NԥQޖVܮޝWܼG SKӕLKӧS
DWKDQG WKQG WURQJWҫPWD\
JDOOHG ܳܧޝO NKyFKӏX
PHVV\ ޖPHVL OӝQ[ӝQ
VFUXQFKXS VNUݞQWݕݞS WKXGӑQ
URWWHQ ޖUܥWԥQ WKӕLUӳD
REMHFWHG ޖܥEGݤܼNW SKҧQÿӕL
HYROYH ܼޖYܥOY WLӃQKyD
REOLJLQJO\ ԥޖEODܼGݤܼƾOL PDQJѫQ
VWDUHG VWHԥU QKuQFKҵPFKҵP
LQWULJXHG ܼQޖWULޝܳ EӏWKXK~W
DQWLFLSDWHG QޖWܼVܼSHܼW GӵÿRiQWUѭӟF
UHOLHI UܼޖOLޝI VӵFӭXWӃ
H[FHSWLRQ ܼNޖVHSݕԥQ QJRҥLOӋ
LQFUHDVH ܼQޖNULޝV WăQJ
FKDVLQJWDLO WݕHܼVWHܼO ÿLOzQJYzQJ
KDQGOH ޖKQGԥO [ӱOê
DOJRULWKP ޖOܳԥUܼèԥP WKXұWWRiQ
PRGLILHG ޖPܥGܼIDܼG VӱDÿәL
GLYLGH GܼޖYDܼG FKLD
FRPSRVLWH ޖNܥPSԥ]ܼW ÿDKӧS
LUUHOHYDQW ܼޖUHOԥYԥQW NK{QJOLrQTXDQ
DSSURDFK ԥޖSUԥݜWݕ FiFKWLӃSFұQ
DPD]HG ԥޖPHܼ]G NLQKQJҥF
VQHDNXS VQLNݞS OҿQOrQ
VWXPEOHXSRQ ޖVWݞPEԥOԥޖSܥQ YҩSQJm
LQFKLQJ ܼQ QKtFKWӯQJFK~W
while(!(success = try()));
www.codegym.vn / Page 51
GLP GܼP OӡPӡ
LJQRUH ܼܳޖQܧޝU /jP
JHQHUDO ޖGݤHQԥUԥO FKXQJ
EUDLQFHOOV EUHܼQVHO WӃEjRQmR
FORVHU NOԥݜ]HU JҫQQ
ULGLFXORXV ޖGܼNMԥOԥV OӕEӏFK
SUHVXPH SUܼޖ]MXޝP SKӓQJÿRiQ
PRGLILFDWLRQ ޙPܥGܼIܼޖNHܼݕԥQ VӵVӱDÿәL
FRQFHUWHG NԥQޖVܮޝWܼG SKӕLS
DWKDQG WKQG WURQJWҫPWD\
JDOOHG ܳܧޝO NKyFKӏX
PHVV\ ޖPHVL OӝQ[ӝQ
VFUXQFKXS VNUݞQWݕݞS WKXGӑQ
URWWHQ ޖUܥWԥQ WKӕLUӳD
REMHFWHG ޖܥEܼNW SKҧQÿӕL
HYROYH ܼޖYܥOY WLӃQKyD
REOLJLQJO\ ԥޖEODܼܼƾOL PDQJѫQ
VWDUHG VWHԥU QKuQFKҵPFKҵP
LQWULJXHG ܼQޖWULޝܳ EӏWKXK~W
DQWLFLSDWHG QޖWܼVܼSHܼW GӵÿRiQWUѭӟF
UHOLHI ޖOLޝI VӵFӭXWӃ
H[FHSWLRQ ܼNޖVHSݕԥQ QJRҥL
LQFUHDVH ܼQޖNULޝV WăQJ
FKDVLQJWDLO HܼVWHܼO ÿLOzQJYzQJ
KDQGOH ޖKQGԥO [ӱ
DOJRULWKP ޖOܳԥèԥP WKXұWWRiQ
PRGLILHG ޖPܥGܼIG VӱDÿәL
GLYLGH ޖYDܼG FKLD
FRPSRVLWH ޖNܥPSԥW ÿDS
LUUHOHYDQW ܼޖUHOԥYԥQW NK{QJOLrQTXDQ
DSSURDFK ԥޖSUԥݜWݕ FiFKWLӃSFұQ
DPD]HG ԥޖPHܼ]G NLQKQJҥF
VQHDNXS VQLNݞS OҿQOrQ
VWXPEOHXSRQ ޖVWݞPEԥOԥޖSܥQ YҩSQJm
LQFKLQJ ܼQWݕ QKtFKWӯQJFK~W
while(!(success = try()));
www.codegym.vn / Page 52
wonder Jerry deleted the first one.
chy nhanh hơn na. Hèn chi Jerry đã
xoá đi phiên bn đầu.
What amazed me, and still amazes
me, is that we snuck up on the better
solution one test case at a time. I don’t
think I would ever have stumbled
upon this simple approach had we not
been inching forward one simple test
case at a time.
I wonder if that happens in bigger
projects? I learned something today.
Ðiu làm tôi kinh ngạc vn còn
làm tôi kinh ngc sau mi kim th
chúng tôi li tiến gần hơn vi gii
pháp. Nếu không tiến lên vi mi
kim th thì tôi không nghĩ s th
đến theo cách đơn gin này.
Tôi không biết chuyn s xy ra vi
nhng d án ln hơn na? Hôm nay
tôi đã hc được đôi điu.
DPD]HG ԥޖPHܼ]G NLQKQJҥF
VQHDNXS VQLNݞS OҿQOrQ
VWXPEOHXSRQ ޖVWݞPEԥOԥޖSܥQ YҩSQJm
LQFKLQJ ܼQ QKtFKWӯQJFK~W
PHỤ LỤC: TÀI NGUYÊN LẬP TRÌNH
Bên cạnh việc học tiếng Anh, bạn có thể tự học lập trình thông qua các tài liệu, khoá học
miễn phí do CodeGym cung cấp:
1. Kho tài liệu lập trình miễn phí: https://codegym.vn/tai-nguyen-hoc-lap-trinh/
Tải nguyên học lập trình trang tổng hợp +200 tài liệu, sách, khoá học, bài thực hành,
video hướng dẫn lập trình… từ bản đến nâng cao, đa dạng chủ đề, phù hợp với mọi
đối tượng từ các bạn bắt đầu học từ con số 0, cho tới những người đang học/làm lập trình
mong muốn nâng cao trình độ, kỹ thuật code…
2. Blog của CodeGym: https://codegym.vn/blog
Đây là nơi tập hợp nhiều bài viết liên quan đến việc học lập trình, bao gồm cả các bài viết
kỹ thuật, các bài viết về công nghệ và cả các bài viết định hướng về nghề nghiệp.
3. GitHub của CodeGym https://github.com/codegym-vn
Đây nơi tập trung các nguồn CodeGym sử dụng trong quá trình dạy học, các
bạn có thể tìm thấy ở đây hàng trăm mã nguồn để tham khảo thuộc các công nghệ khác
nhau như Java, PHP, .NET, Javascript, Android, React...
4. Ứng dụng luyện tập CodeGym Bob: https://bob.codegym.vn/home
Đây là ứng dụng rất phù hợp cho những bạn mới bắt đầu đến để luyện tập khẳng định
các năng lực của mình. Ứng dụng này hoàn toàn miễn phí và sẽ tự động giúp bạn đánh
giá mức độ thuần thục của mình trong việc áp dụng các kiến thức đã học được.
5. Nhóm Học lập trình: https:// facebook.com/groups/hoclaptrinh.cg
Đây là nơi mà những người mới bắt đầu học lập trình có thể tham gia và thảo luận, nhận
được các tư vấn và lời khuyên từ những người đi trước.
6. Các trang web chia sẻ kiến thức hữu ích về các công nghệ
• Học Java: https://hocjava.com
• Học PHP: https://hocphp.net
• Học Laravel: https://hoclaravel.net
• Học Spring MVC: https://hocspringmvc.net
• Học Spring Boot: https://hocspringboot.net
• Học Javascript: https://hocjavascript.net
while(!(success = try()));
www.codegym.vn / Page 53